OmniAICreator/Qiita-1.07M huggingface dataset:
Braveブラウザについて

# 概要
この記事では、近年のホットワードである「Web3.0」への遷移に伴い、登場した新しいコンセプトのブラウザである「Braveブラウザ」について紹介します。
# Braveブラウザとは
![brave-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779963/597d30ac-88c3-a502-caae-ee3644160d6c.png)
2019年にBrave Softwareによって開発されたウェブブラウザでです。
特徴は以下があります。
- 「ページの高速表示」と「プライバシー保護」に特化した、新しいウェブブラウザ
- 新しいビジネスモデルを構築している
- ネットサーフィンをするだけで仮想通貨が手に入る。
## Web3.0とは
一言でいうと、打倒GAFAの動きです。
これまでの、Web2.0ではGAFAのような中央集権型でした。GAFAのようなプラットフォーマーがデータを管理していました。
つまり企業が個人データを管理する、という時代でした。SNSのような双方向性や自由が保障されるように見えつつも、「場」の提供者に情報や力が集中してしまうという側面もありました。
ここでいうWeb3.0とは、プラットフォームから分散させてユーザー個人で管理を行っていこうという動きです。
これまでプラットフォーマーに集中していた情報を「企業」→「個人」で管理します。
データ管理や取引にはブロックチェーンを用います。中央集権ではなくなるため、情報が政府に渡ったりハッカーによる情報漏洩が少なくなります。
また、言論の自由がより担保され、セキュリティの高いサービスを利用できるようにもなります。
まとめると、以下の特徴となります。
- Web3.0では企業が情報の管理を行わず、ユーザー個人で管理を行う
- 中央集権がないので、情報を政府に渡したり、ハッカーによる情報漏洩が少なくなる
- 非中央集権化することで言論の自由が保障されるほか、よりセキュリティの高いサービスを利用できる

## ビジネスモデル
Braveブラウザの特徴的な要素の1つはビジネスモデルです。
それは、「原則すべての広告をブロックし、設定により広告量を調整し、見た広告量に対して報酬を仮想通貨(BAT)でもらうことができる」という点です。
ざっくりと、まとめると以下のフローとなります。
1. 広告主(パブリッシャー。コンテンツクリエイター)は、仮想通貨(BAT)を買い、Braveの広告配信システムに登録する。
2. ユーザーは、自分で見る広告量を登録する
3. ユーザーの設定に応じて広告が流れる
4. 実際に流れた、広告量に応じて仮想通貨(BAT)を受け取る

という流れです。
広告量を自分で制限することができるため、「ページの高速表示」につながります。
例えば、YouTubeでの広告もChromeの拡張機能のAdBlock無しで流れなくなります。

公式サイトによると、閲覧した広告収益の70%を還元しているようです。

## メリット
- 高速なブラウジング
    - 広告を表示しないので、他のブラウザに比べてページ読み込みがPCで2倍、スマホで最大8倍速くなります。また、youtubeなどの広告もブロックしてくれます。
- Chromiumベースの利点としてGoogle Chrome向けの拡張機能を利用できる
    - シェア率が64.95%のgoogle chlomeの拡張機能をそのまま利用できるので、ストレスフリーでBraveに以降することができます。
- 省電力／通信容量の削減
    - 他ブラウザと比較すると広告量減少による効果で、スマホのバッテリー消費量が35%減、スマホのメモリ消費量が最大66%減と優れています。
- お金が稼げる
    - BraveRewordをオンにすると広告が表示されます。ただ表示する量を自分で調節でき、その対価として報酬をもらうことができます。


## BATについて
![basic-attention-token-bat-logo-300x300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779963/cf66a817-831b-bd6b-8b4f-51faa9769f68.png)
BATは、仮想通貨の1つです。
BATには、投げ銭としての機能があります。
YouTubeやTwitter、GitHubなど、コンテンツクリエイターに対してBATで送金することができます。
既存の円やドルでの投げ銭と比較して、貨幣の一元化、送金手数料、送金時間の短縮において優れています。

執筆日(2022/12/15)のBATは、29.928円/BATです。約1年前には、200円台に乗った時もあったので、現在は1/6の価値となっています...
ここが、仮想通貨の投機性と言われる側面だと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779963/c16ac643-c9a6-4f17-674c-cee32aee3958.png)
<div class="tradingview-widget-copyright">TradingView提供の<a href="https://jp.tradingview.com/symbols/BATUSDT/?exchange=BINANCE" rel="noopener" target="_blank"><span class="blue-text">BATUSDTチャート</span></a></div>

# おわりに
「Web2.0」→「Web3.0」への遷移で、Braveブラウザ以外にもサービスがたくさん出ていました。
覚えることもサービスも多く、追っていくのも大変ですが、こういう画期的なビジネスモデルを取り入れたサービスは利用以外の側面からも面白いと思えるので記事作成自体は楽しかったです。
SlackやYouTube、Spotifyなどにも代替サービスが出ているみたいなので、触ってみたいなと思いました。
ReactとWebpack

```
npm init
```

```
npm install react react-dom
```

```
npm install --save-dev webpack webpack-cli html-webpack-plugin css-loader style-loader
```

```
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react 
```

webpack.config.js
```
const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
        index: './src/index.js',
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: { presets: ['@babel/preset-env', '@babel/react'] },
                    },
                ]
            },
        ],
    },
};

```

index.html
```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
  </head>
  <body>
    <div id="root"></div>
    <script defer src="/dist/index.bundle.js"></script>
  </body>
</html>
```

src/index.js
```
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './app.js';

const root = createRoot(
    document.getElementById('root')
);

const element = <App />;
root.render(element);
```

src/app.js
```
import React from 'react';

const App = () => {
    return(
        <div><h1>Hello World React</h1></div>
    )
}

export default App;
```


ビルド
```
npx webpack
```
linux/windows copy and create destination dir if it does not exist (c++)

### linux
```bash
mkdir -p "$d" && cp file "$d"
```

### windows
```batch
xcopy file.txt c:\new\path\file.txt*
```
/y overwrite
```
* -> file
```

### c++
```cpp
//std::string command = "xcopy file.txt c:\\new\\path\\file.txt*";
std::ostringstream oss;
oss << "xcopy " <<"\""<<entry.path().string() << "\"" << " " << destanation << "*"; // prevent space in source path
std::string command = oss.str();
system(command.c_str());
```
【自分用メモ】Pythonを使ったアルゴリズムの学習

投稿日：2022/11/20
Pythonを使ったアルゴリズムの学習を行いました。
理解したことを、自分用のメモとして残します。

## 入力された2つの値の総和を求めるプログラムを作成せよ

~~~ python:自分の回答
num1 = input("好きな整数を入力してください")
num2 = input("好きな整数をもう一つ入力してください")

print(num1, "と", num2, "が入力されました。")
print("入力された整数の合計は", int(num1) + int(num2), "です。")
~~~

~~~:出力結果
4 と 8 が入力されました。
入力された整数の合計は 12 です。
~~~

~~~ python:模範解答
# リスト内包表記：既存のリストから取り出した要素に対し処理
# [xの処理 for x in 配列など]
# 2つの整数を空白で区切り、文字列として受け取る A, B, C = input().split()
# int(x)：データ型の変換、文字列 → 整数
num1, num2 = (int(x) for x in input("空白を開けて整数を2つ入力して下さい").split())
print(num1 + num2)
~~~

~~~ :出力結果
空白を開けて数字を2つ入力して下さい7 4
11
~~~

### 参考文献

以下の記事を参考にさせていただきました。

https://qiita.com/KTakahiro1729/items/c9cb757473de50652374

https://qiita.com/kyuna/items/8ee8916c2f4e36321a1c
HTMLでダウンロードリンクを作る方法

# HTMLでダウンロードリンクを作る

製作中のwebサイトでダウンロードリンクを作ることがあったので、自分のメモ程度に残しておきます。このやり方はクリックした際、リンク先のファイルを表示せずにダウンロードを開始します。
<br/>
## 完成系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632237/7748f3d9-c138-8e17-bee6-92c6fcc37171.png)
ダウンロードリンク（.zip）を押すとダウンロードが開始されます。

## やり方

```HTML
<a href="./zipbox/Maze.zip" download="Maze.zip">
  <strong>ダウンロードリンク(.zip)</strong>
<a>
```
``href=""``にはリンク先のURLを指定します。
``download=""``にはダウンロードされたときのファイル名を指定します。
今回は同じファイル階層にzipboxというディレクトリを作っています。zipboxは.zipファイルを入れておくディレクトリです。
IBM Qiskit：量子回路の作成・可視化 〜 バックエンド定義 まで & 量子ゲートに関する調査

# IBM Qiskit の試用

from `qiskit-tutorials/qiskit/tutorials/circuits/1_getting_started_with_qiskit.ipynb` in IBMQuantum Lab

**量子回路の作成・可視化** 〜 **バックエンド定義** まで実施

## パッケージのインポート

```python
import numpy as np
from qiskit import *
```

## 量子回路の作成

```python
# Create a Quantum Circuit acting on a quantum register of three qubits
circ = QuantumCircuit(3)
```

## ゲートの追加

追加したゲートの役割は「量子ゲートに関する調査」の項に記載

```python
# Add a H gate on qubit 0, putting this qubit in superposition.
circ.h(0)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
circ.cx(0, 1)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting
# the qubits in a GHZ state.
circ.cx(0, 2)
# <qiskit.circuit.instructionset.InstructionSet at 0x7f13df5667c0>
```

## 量子回路の可視化

```python
circ.draw('mpl')
```
▼ 出力された回路図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2926049/f10125f3-2e43-2fb5-8f5d-a40d376a04cd.png)

## **Qiskit Aer（量子回路シミュレータ）のバックエンド定義**

```python
from qiskit import Aer

# 回路を実行するためのバックエンドを定義
backend = Aer.get_backend('statevector_simulator')

# <frozen importlib._bootstrap>:219: RuntimeWarning: scipy._lib.messagestream.MessageStream size changed, may indicate binary incompatibility. Expected 56 from C header, got 64 from PyObject
```

## **参考**

IBM の Qiskit ドキュメント
[Introduction to Qiskit - Qiskit 0.39.2 documentation](https://qiskit.org/documentation/intro_tutorial1.html)

# 量子ゲートに関する調査

## 代表的なゲート

1. パウリゲート
2. アダマールゲート

Why: 1, 2 と共に**自己随伴行列**

## アダマールゲート

基底状態の量子ビットを重ね合わせの状態へ移すために用いる

Why: アダマールゲートの定義（回転行列？）と状態遷移（基底 → 重ね合わせ）の対応付け

**定義**

$$
\boldsymbol H = 
\frac{1}{\sqrt{2}}
\begin{bmatrix}
1 & 1 \\\\
1 & -1
\end{bmatrix}
$$

## 参考
Microsoft/QuantumKatas の Binder Notebook
[GitHub: Microsoft/QuantumKatas/42ee33b0001df1f74682c9ac0f5523d644708bdd](https://mybinder.org/v2/gh/Microsoft/QuantumKatas/42ee33b0001df1f74682c9ac0f5523d644708bdd)
【Xcode】archiveでerror【undefined symbol: 】

# はじめに
・Xcodeにて、build => warning で、successする。
アプリ自体は立ち上がるため、リリースするためapp-connectに送ろうとしました。
・Xcodeにて、archive => error2件発生（どちらも、undefined symbol:~）
errorの内容の解決策がわからない。。。
・ターミナルにて、pod install => ターミナルでwarningあり 
ずっと無視してたので、この際pod installの方を解消しようと試みます。
　
ちなみにSakadachiTimerはアプリ名ですので、それぞれのアプリ名に変換してこの記事を参照してください。

# pod install　ワーニング内容
```:terminal
[!] The `SakadachiTimer [Debug]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-SakadachiTimer/Pods-SakadachiTimer.debug.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

[!] The `SakadachiTimer [Release]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-SakadachiTimer/Pods-SakadachiTimer.release.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.
```

# 環境
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   MacOS Monterey ver 12.5.1     |
| 2  |      Xcode     |   14.1 |
| 3 |     Swift     |   5.7.1|

# 結論

【Pods/Target Support Files/Pods-SakadachiTimer/Pods-SakadachiTimer.release.xcconfig】を開き、「ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES」 をコメントアウトする。
同様に、【Pods/Target Support Files/Pods-SakadachiTimer/Pods-SakadachiTimer.debug.xcconfig】も対応。

![スクリーンショット 2022-11-16 2.27.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/8eabbf6b-38b4-0071-ae4f-55eb7f87cb73.png)
![スクリーンショット 2022-11-21 16.29.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/b7382b88-856c-f796-61a0-1cf9096f02cc.png)

これでpod installをしてみる！

　
　
　
が、同じワーニングが表示された。。。
　
一応archiveをしてみると、、、通った！
エラーが消えて、無事リリースできました。
# おわりに
pod installの方は解消できなかったけど、それ関連のarchiveでのエラーは直ったのでよしとします。
MacでChromedriverへのパスの通し方

学習を始めたばかりですが、自分がとても役に立ったと思うものを記録していけたらと思います。

Chromedriverのパスの通し方がわからなかった時とても役に立った。
https://watlab-blog.com/2019/08/10/chromedriver-path/
twitter api v1からv2へ(その2）

# はじめに
　[twitter api v1からv2へ](https://qiita.com/hawaii_hahaha/items/479639dd5e656ecba5e7)を書いたが、oauth pkceについてはまだだったのでそのご報告

# 手順
　1)twitter developerでの登録
```
　　App permissions=Read and write and Direct message
   Type of App=Web App, Automated App or Bot
   App info
     Callback URI / Redirect URL=http://127.0.0.1:3000/callback
     Website URL=https://twitter.com/
 　　以下は入力していない
```     
  そして、そのあと、Keys and tokensのタブにいって、最後のOAuth 2.0 Client ID and Client Secretの部分で、Client IDとClient Secretをメモする・・といってもcopyしてenvに設定する。
  2)[twitter-sdk](https://github.com/twitterdev/twitter-api-typescript-sdk)のinstall
   上のlinkはgitそのままだが、 npm i twitter-api-sdkでダウンロードできる。
　　そのあと、npm i express,@types/express,dotenv

  3)copyと環境設定
　　https://github.com/twitterdev/twitter-api-typescript-sdk のexampleから
　　oauth2-callback_pkce_plain.tsをもってくる。とりあえず、login.tsとした。
　　環境変数にCLIENT_IDとCLIENT_SECRETを設定する、設定する値は1)で取得した値

  4)実行
　　npx ts-node login.ts
    で、Go here to login: http://127.0.0.1:3000/login
　　というメッセージがでたら、  自分のchromeとかで上のアドレスを叩く
　　すると、twitterの画面が出てきて承認しろといわれるので、okする。

　5)確認
　　認証後のtweetメッセージが自分のchrome上に表示されるので、これでok

# twitter-api-sdkのドキュメント
　installしたnode_module/twitter-api-sdk/dist/gen/client.d.tsあたりに、関数の呼び方の一覧があるので、これを読みながら、関数を探す。timelineを探すと
　client.tweets.usersIdTimeline('userid')という形で呼び出せば、/2/users/:id/timelines/reverse_chronologicalを呼び出すということで、これも成功

　ちなみに、typescriptではなくjavascriptでも大して変わらない。importをrequireに変更してas Stringとかの設定を削除すれば、無事node login.jsということで動く。私はこれで実験した。

あとはよしなに
DDDがわからない～誰がためのルールか～

# 誰がためのルールか
開発すための決まりごとは、開発する関係者全員の負荷を分散し楽をするために作られるべきです。そのルールを決めたことで誰かが楽できるのであれば、そのルールに従う負荷と比較してルールとして決定しましょう。もし、そのルールに従ったとして誰も楽できないのであればルールとするべきではありません。

# 独自の表現(名前)を作り出さない
新たな表現をしたいときには影響するメンバー全員に周知する。
これは、ズレの最大の原因ですのでこれは必須としましょう

# 細かい実装は、個人に任せる
個人の担当分でしか影響しない実装であれば、ある程度コーディングについては許容する。
ただし、限度というものがあるのでプログラマー同士でチェックは行う。
jq コマンドでオブジェクトの配列を範囲指定する

```sh
echo '[{"a":1,"b":2},{"a":3,"b":4},{"a":5, "b":6}]' | jq '.[0:2][].a'

1
3
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Google AppSheetでプルダウンを使う

# はじめに
AppSheetを初めて触ってみたのですが、既存のテキストをプルダウンにするだけでもちょっと苦労しました。
せっかく試してみたので、記録として残しておこうかと思います。
※今回は、テンプレートアプリの一部分をプルダウンに変更するというものです。

# 前提
AppSheetであらかじめ用意されているテンプレートアプリを入れてあるところから開始します。
元々テキスト入力エリアだった部分をプルダウンに変更していきます。

# テーブルとレコードの追加
まず、プルダウンリストの値を格納するためのテーブルを作成します。
「New Table」から追加できます。
![no01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/0c1596c4-f34f-443d-10e5-cffb7ee9afe6.png)

今回は勤怠申請をイメージして、以下のような値を登録していきます。
![no02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/76bb9eb0-2ed0-cc8e-239b-740dfcf7e67c.png)

# プルダウンの設定とデータの紐づけ
アプリの編集画面から、今回変更したいデータを選択します。
![no03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/76ef4a1d-4038-48a9-fa2f-115f335ed1a1.png)

現在使用されているテーブルカラム情報が表示されます。
画像の赤枠部分から設定の編集を行います。
![no04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/44a16f86-5ea5-19fe-50f0-3b41be3aa657.png)

Source Tableという欄で、先ほど作成したテーブルを選択します。
次に、Input ModeでDropdownを選択します。
![no05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/d607c63a-b5dd-2f59-f5d1-20fa28580a77.png)
やることは以上です。

# 表示確認
作成しているアプリのプレビューを確認します。
選択するとプルダウンが表示されます。
![no06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/02f3a63b-359d-d2af-f5f7-c5fb9b0251a5.png)
![no07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008719/2c8d0de1-904d-8a98-14ed-f2c896d4add2.png)

これで終わりです。
Carbonを使おう

# Carbonとは
phpのDateTimeクラスをオーバーラップした日付操作ライブラリ
Carbonには便利なメソッドが揃っているので、日付の操作をDateTimeクラスで色々いじるよりは
簡単に解決できるかも

# インストール
Composerを使ってインストール

# 準備
autoload.phpを呼ぶ
```carbon.php
require 'vendor/autoload.php';
```
# Carbonの使い方
## インスタンス生成
```carbon.php
// new
$carbon = new Carbon();

// 静的
$carbon = Carbon::now();

// 日付け指定
$carbon = new Carbon("2022-11-21");

// 静的
$carbon = Carbon::parse("2022-11-21");
```

## 日付けフォーマット
```carbon.php
$carbon->format('Y-m-d');
// 2022-11-21
```
## 日付の取得
```carbon.php
今日
$carbon::today()->format('Y-m-d H:i:s'));
// 2022-11-21"
昨日
$carbon::yesterday()->format('Y-m-d H:i:s'));
// 2022-11-20
明日
$carbon::tomorrow()->format('Y-m-d H:i:s'));
// 2022-11-22
```

## 日付の加減算
```carbon.php
※元の値を操作したくない場合はcopy()メソッドを使用
年追加
$carbon->copy()->addYear(1)->format('Y-m-d H:i:s');
// 2023-11-21
月追加
$carbon->copy()->addMonth(1)->format('Y-m-d H:i:s');
// 2022-12-21
日追加
$carbon->copy()->addDay(1)->format('Y-m-d H:i:s');
// 2022-11-22
1週追加
$carbon->copy()->addWeek(1)->format('Y-m-d H:i:s');
// 2022-11-28

月あふれの場合 1月31日にして1カ月足すと
$carbon->copy()->setDate(2022, 1, 31)->addMonth(1)->format('Y-m-d');
// 2022-03-03

月あふれさせない場合
$carbon->copy()->setDate(2022, 1, 31)->addMonthWithoutOverflow(1)->format('Y-m-d');
// 2022-02-28
// あふれさせたくない場合はWithoutOverflowメソッドを使用する(例, 年) addYearsWithoutOverflow)

年の差分
$carbon_diff = $carbon::parse("2020-09-01");
$carbon->diffInYears($carbon_diff);
// 2

月の差分
$carbon->diffInMonths($carbon_diff);
// 26

日の差分
$carbon->diffInDays($carbon_diff);
// 811

他にもいろいろ
addHour()
addMinute()
addSecond()
addMillisecond()
addMicro()
addMillennium()
addCentury()
addDecade()
addQuarter()
addWeek()

減算系は
基本的にaddをsubに
使い方は大体同じ
subYear();
subMonth();
subDay();
```

## 日付の取得
```carbon.php
年の取得
$carbon->year
// 2022

月の取得
$carbon->month;
// 11

日取得
$carbon->day;
// 21

時の取得
$carbon->hour(14);
$carbon->hour;

// 14

分の取得
$carbon->minute(22);
$carbon->minute);
// 22

秒の取得
$carbon->second(30);
$carbon->second
// 30

日本名とかの取得
setLocale('ja')で日本語に
Carbon::setLocale('ja');

曜日名(短縮)
$carbon->getTranslatedMinDayName());
// 月

曜日名
$carbon->getTranslatedDayName());
// 月曜日

月名
$carbon->getTranslatedMonthName());
// 11月

年の何日目か
$carbon->dayOfYear();
// 325

月の何週目か ※月曜始まり
$carbon->weekNumberInMonth;
// 4

年の何週目か
$carbon->weekNumberInMonth;
// 47

月の日数
$carbon->daysInMonth;
// 30

日付取得
$carbon->toDateString();
// 2022-11-21

時刻取得
$carbon->hour(14);
$carbon->minute(22);
$carbon->second(30);
$carbon->toTimeString();
// 14:22:30
```

## 日付判定
```carbon.php
未来
$carbon->isFuture();
// false

過去
$carbon->isPast();
// ture

今日
$carbon->isToday();
// true

平日
$carbon->isWeekday();
// true

週末(土日)
$carbon->isWeekend());
// false

月曜日
$carbon->isMonday();
// true
// 月～日までメソッドがあるよ

日付範囲
Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'));
// true

誕生日
$carbon->isBirthday((new Carbon())->setDate(2022, 1, 31)));
// false
$carbon->isBirthday((new Carbon())::now()));
// true

うるう年
$carbon->isLeapYear();
// false
```
自社の「ワンデー仕事体験」プログラムを改善する話

# 自社の「ワンデー仕事体験」プログラムを改善する話
昨年度、社内チームメンバーと協力して、自社の「ワンデー仕事体験」のプログラムを作成しました。
(その際のQiita記事はこちら)https://qiita.com/hori-ap099/items/a7e94fd4f2107be1cdd6

今年度は、作成した「ワンデー仕事体験」プログラムで発生した課題を改善したので、改善内容と躓いた点などを記載しようと思います。

## 発生した課題と改善案
ワンデー仕事体験は、学生にハッキングを体験してもらう性質上、隔離されたネットワークを毎回構築しております。

ネットワーク構成イメージ
![現行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514526/738650ab-d6f2-4003-9f35-19d39fd25361.png)

また、windows10のPCでは、コンピュータのセキュリティ対策ソフトを落とす作業も行っており、慣れている人でも準備に1時間以上掛かっております。
設定ミスがあった場合ワンデー仕事体験中に疎通できなくなるなどの問題もあり
・準備に時間が掛かってしまう点
・設定ミスを起こさないようにする点
を早めに解決する必要がありました。

そのため改善案としては、"設定が固定できる環境"を用意することで、準備に掛かる時間も同時に短縮できるので、AWS上に環境を構築、ワンデー仕事体験の際にRDPで接続するようにする方針となりました。
この改善で、1時間以上かかっていた準備が30分も掛からず完了する見込みとなっております。

## 検証環境
検証時のAWS内ネットワーク構成案は下記の通りです。
![AWS設計b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514526/884f42d3-aac6-0c6b-409a-ddb497fcc032.png)

検証の為、インターネットゲートウェイとPublic subnet間は3389/TCPのみ許可し、
Public subnetとPrivate subnet間は特に通信制限を設けない設定にしました。

## 検証時の問題点
検証中に発生した大きな問題としては、Kali LinuxからWindowsデスクトップのスクリーンショットを撮る検証をしていた際、スクリーンショットが撮れない問題がありました。
明確な原因は不明でしたが、RDPが接続された状態でスクリーンショットが撮れない、もしくは仮想環境上ではスクリーンショットが撮れない等の原因が考えられた為、
Kali Linuxから`screenshot`コマンドを実行する形から、Windows内にpowershellのマクロを用意し、スクリーンショットを撮る方法に変更しました。

#### 手順
前提:Kali LinuxとWindowsのsessionが確立している状態
1.Kali Linuxで`shell`を実行し、Windowsに入る
2.`powershell xxxx.ps1 yyyy.png`でpowershellのマクロを実行
3.`exit`でKali Linuxに戻り、`download yyyy.png`でスクリーンショットしたファイルをダウンロードする

<details><summary>powershellのマクロ</summary>

```rb
# screenshot-primary.ps1
# From https://stackoverflow.com/questions/2969321/how-can-i-do-a-screen-capture-in-windows-powershell
Add-Type -AssemblyName System.Windows.Forms,System.Drawing

$screen = [Windows.Forms.Screen]::PrimaryScreen

$top    = $screen.Bounds.Top
$left   = $screen.Bounds.Left
#$right  = $screen.Bounds.Right
#$bottom = $screen.Bounds.Bottom
$right  = 2000 #幅のサイズを指定する
$bottom = 2000 #高さのサイズを指定する

$bounds   = [Drawing.Rectangle]::FromLTRB($left, $top, $right, $bottom)
$bmp      = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height)
$graphics = [Drawing.Graphics]::FromImage($bmp)

$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)

$bmp.Save($Args[0])

$graphics.Dispose()
$bmp.Dispose() >

```
</details>


## 今回の件で学んだこと
私個人の話になってしまいますが、AWSの環境を触ることがあまり無かったため、環境構築と検証は良い刺激になりました。
この規模でも環境をAWSに移行する際には、決めることや問題が発生する点等、擬似的なAWSへの移行案件を実施した気分です。
今後も社内や個人でAWS含め経験できることがあれば実施していきたいと思います。
在宅デスクワーカーの仕事環境と健康管理

## 自己紹介
記事をご覧いただきありがとうございます！

私は以前、看護師（歴約10年）をしていましたが
出産を機に退職し、色々あって
2022年8月からフロントエンジニアとして働き始めました。

今はフルリモートで働いております。

看護師の時とは違い
1日の活動時間の半分以上は画面に向かって仕事をしているためか
体に不調が現れ始めています...

具体的には

- 肩こり、腰痛
- 眼精疲労（霞むし、ひどい時は痛みまである）
- 疲労感

年のせい？
まぁ、30代半ばにもなれば色々不調は出てくるものですが
おそらくこれは「VDT作業」による影響だと考えています。

## VDT作業とは
社員の健康管理をきっちりやっている企業に勤めている方は
聞いたことがある人もいるかもしれませんね。
（健康状態についてのアンケートを取られたり、保健師さんが労働環境のチェックに来たりなど、見たことありませんか？）

**VDT作業とは
Visual Display Terminalsの頭文字で
液晶等の画面表示機器と、キーボードやマウス、タッチ画面等の入力機器による
情報端末を使用する作業**

のことです。
（VDTという言葉自体はガイドラインのタイトルから外されたり、あまり使われなくなってきています。）

つまり、我々ITエンジニアはバッチリ該当するわけですね。

今の時代、仕事でPCやモバイルを使うことは当たり前。
下のグラフは平成20年のデータなので少し古いですが
長時間のPC作業による身体症状を訴えている人が少なからずいるのがわかります。
（目の疲労については1時間未満でも結構出てくるようですね...）
<img width="90%" alt="13.36.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982270/2ff457d0-634f-455c-519f-7a34c08f9a00.png">
*「[平成２０年技術革新と労働に関する実態調査結果の概況](https://www.mhlw.go.jp/toukei/itiran/roudou/saigai/anzen/08/dl/20kaku-10_12-26.pdf)（厚生労働省）」を加工して作成*

私の場合、身体的な症状として出てきていますが
精神症状として現れることも。

厚生労働省は1985年に「VDT作業のための労働衛生上の指針」を策定し
ガイドラインを作成（最近では2019年に改定されています）
企業や個人に対して健康管理を促しています。

## 今の作業環境
ちなみに私が今、どんな環境で仕事をしているかというと...
<img width="80%" alt="image0.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982270/15ffe80e-3ac7-bc4d-cb79-a8fdd19fdcc3.jpeg">
ありのままでございます。

こうして見ると、やっぱりお部屋暗いですね。
椅子は写っていませんが、ニ○リで買った2万円くらいの
背もたれ・肘置きありのものを使っています。

## 体調不良の原因（私の場合）
作業環境を専門家に見ていただいたら
もっと問題点が出てくるかもしれませんが
今私が抱える症状から考えるに

**肩こり・腰痛**
- 椅子と机の高さが私の体格に合っていない
- ディスプレイの高さが合っていない

**眼精疲労**
- 部屋の明るさが暗い
- 時間帯によっては陽の光が反射して眩しい
- 目と画面の距離が近い

**疲労感**
- 長時間座りっぱなし
- 長時間連続での作業
- 運動不足

といった感じでしょうか。

## 在宅ワーカーの理想的な作業環境
では、具体的にどんな対策を取れば良いでしょうか？

[厚生労働省のガイドライン](https://www.mhlw.go.jp/content/000539604.pdf)には作業環境に関して細かくアドバイスが載っています。
ちなみに事業所以外で仕事をしている人は[情報通信技術を利用した事業場外勤務の適切な導入及び実施のためのガイドライン](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwip0azsv777AhVJUd4KHTThDGwQFnoECA0QAQ&url=https%3A%2F%2Fwww.mhlw.go.jp%2Fcontent%2F11911500%2F000690830.pdf&usg=AOvVaw0rrsIjg1mwMVoISBoXR1Qu)の「別紙2」も参考になるかと思います。
が、全文を読むのは辛いので厚生労働省のHPに載っている図を見てみましょう。
<img width="80%" alt="14.18.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982270/53e5739c-b37a-9cc7-bf01-54bc1c1a5451.png">
*出典：[厚生労働省ホームページ](https://www.mhlw.go.jp/stf/newpage_01603.html)*

いかがでしょう？
みなさんは、この図のような環境が作れていますか？

## 今後の取り組み
自宅の作業環境を整えようと思っても
**「お金かかるし...」
「とりあえず今の環境でも仕事できてるし...」
「なにより、面倒！」**
となって、ついつい後回しにしてしまいがちですが

**「健康以上の資産はない」**

と私は思っています。
そして

**「自分を守れるのは自分だけ」**

だとも思っています。

一気に全て整えるのは無理でも
ボーナスやネット通販がセールをしている時
お誕生日などなど
何をキッカケにしても良いので
気が向いた時に少しずつ変えていきましょう！

私もガイドラインと照らし合わせるとまだまだ、改善の余地がありそうです。
とりあえず今は眼精疲労の症状が一番辛いので
次のAmaz○nセールでデスク用の照明と反射防止シートを買おうと思います！
「Goのtime.Formatによるミリ秒切り捨て」と「MySQLのINSERTによるミリ秒四捨五入」で1秒の誤差が生まれた話

# 背景
2022年春頃にZOZOTOWNで[ログイン通知機能](https://zozo.jp/_help/default.html?id=6204a11db02e7e001df030c3)と[ログイン履歴機能](https://zozo.jp/_help/default.html?id=6204a0c3d79f060023f5d723)をリリースしました。QAのフェーズにおいて、「ログイン通知で表示されるログイン時刻」と「ログイン履歴で表示されるログイン時刻」で最大1秒の誤差が生まれるケースがあることが判明しました。どちらの時刻もミリ秒までは表示しない仕様です。1秒とはいえ、これらの値が不一致なのは問題なので原因調査と対策をしました。

# 原因
## ログイン通知で表示されるログイン時刻
ログイン通知で表示されるログイン時刻は、サーバがログインリクエストを受け付けた時の日時です。つまり、Goのアプリケーション上でのみ処理するデータです。アプリケーションでは、その日時を下のようにFormatし、ミリ秒を**切り捨て**ます。

```go
package main

import (
	"fmt"
	"time"
)

func main() {
	t, _ := time.Parse("2006/01/02 15:04:05", "2022/04/05 10:00:00.500")
	fmt.Println(t.Format("2006/01/02 15:04:05"))
}
```

```
2022/04/05 10:00:00
```

## ログイン履歴で表示されるログイン時刻
ログイン履歴で表示されるログイン時刻は、一度MySQLのDBにINSERTされたデータをSELECTで取得したデータです。

カラムの型はDATETIMEで、ミリ秒は扱いません。もし、ミリ秒のデータをINSERTするとミリ秒が**四捨五入**されます。

```
mysql> INSERT INTO test VALUES (CAST('2022/04/05 10:00:00.500' as datetime));
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM test;
+---------------------+
| t                   |
+---------------------+
| 2022-04-05 10:00:01 |
+---------------------+
1 row in set (0.00 sec)
```

## 原因まとめ
上記の通り、「ログイン通知で表示されるログイン時刻」はGoのtimeパッケージのFormatでミリ秒以下が切り捨てられるのに対して、「ログイン履歴で表示されるログイン時刻」はMySQLのINSERTによりミリ秒以下が四捨五入されることが原因でした。

# 対策
ログイン履歴情報をDBにINSERTする前に、時刻情報のミリ秒を切り捨てるように改修しました。
vim-plugのPlugInstallでfatal could not read remote repositoryになったときの対処法

git push するときにパスワード入力をssh通信によって省略するためにレポジトリのurlを置き換える処理をする設定をしていたために生じたエラー

# before

```:~/.ssh/config
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/github
  User git
```

```:~/.gitconfig
[url "github:"]
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:
```

# after

```:~/.gitconfig
[url "github:"]
    pushInsteadOf = https://github.com/
    pushInsteadOf = git@github.com:
```

# 解決方法

`InsteadOf`を`pushInsteadOf`にしてpushのときのみurlを置き換えるように変更したところPlugInstallできるようになった
jQueryで1日1回、初回アクセス時のみモーダルを表示するサンプル

1日の中で最初にアクセスした時のみモーダルを表示させるサンプルです。
初回アクセスかどうかはCookieを使って判別します。

CookieはjQueryのプラグインを使って簡単に操作できます。
今まで使っていた **jquery.cookie.js** はサポート終了して **js-cookie** に移行しているので、
今回はそちらを使って実装してみました。

# 仕様

- アクセス時にCookieを保存する
- 初回アクセス時（Cookieが保存されていない場合）のみモーダルを表示する
- 2回目のアクセス以降、Cookieが保存されている間はモーダルを表示しない
- 翌日の0時にCookieをリセット（有効期限切れ）する

# js-cookie

https://github.com/js-cookie/js-cookie

Cookieの取得や保存を簡単に行うことができます。
基本的な書き方は以下の通り。

```js:取得
Cookies.get('[名前]');
```

```js:保存
Cookies.set('[名前]', '[値]', { expires: [有効期限] });
```

```js:削除
Cookies.remove('[名前]');
```

# サンプルコード

```html:HTML
<script src="/js/js.cookie.min.js"></script>
```

```js:JavaScript
$(function() {
	const date = new Date();
	date.setDate(date.getDate() + 1);
	date.setHours(0, 0, 0);
	if (Cookies.get('access_sample') == undefined) {
		Cookies.set('access_sample', 'access', { expires: date });
		$('.modal').fadeIn();
	}
});
```

### Cookieの有効期限

初回アクセスかどうかを判別するため、有効期限付きのCookieを保存します。
有効期限はアクセスした日の翌日の0時とします。

```js
const date = new Date();
date.setDate(date.getDate() + 1);
date.setHours(0, 0, 0);
```

`date.getDate() + 1` で取得した日付（アクセスした日付）の翌日の日付にすることができます。
この際、11月30日から12月1日のように月をまたぐ場合も自動で計算してくれます。

これで `date` に「アクセスした日の翌日の0時」が格納されました。

### Cookieの有無をチェック

`Cookies.get()` で保存されているCookieを取得することができます。
指定した名前のCookieが保存されていない場合、Cookieを保存してモーダルを表示します。

```js
if (Cookies.get('access_sample') == undefined) {
	Cookies.set('access_sample', 'access', { expires: date });
	$('.modal').fadeIn();
}
```

`Cookies.set()` でCookieの名前、値、有効期限を指定して保存することができます。

`expires` はCookieの有効期限を指定できるオプションです。
変数で指定せずに数字で指定することも可能です。
例えば `expires: 1` と指定すると1日（24時間）後が有効期限となります。

# まとめ

簡単に操作できて便利すぎる。
頻度を変えたりモーダル以外の表示に使用したりできるので、ぜひ活用してください。
【T-watch】見た目もよいスマートウォッチを格安で作る

# 1.はじめに
以前、スマートウォッチを以下記事のように作成した。しかし、見た目があまりよろしくなかった上に、電池が持たないため、普段使いすることはなかった。

https://qiita.com/ojitani3/items/0f41327723a43ebf8fc8


そこで、前回のスマートウォッチ製作よりも見た目が良いスマートウォッチ＆電池持ちがいいスマートウォッチを、今回の記事で作成する。





# 2.使う材料
2-1.スマートウォッチ本体
Aliexpressで販売されている、TTGO社製のT-Watch2020 V1を使用する。
セール時にはかなり安くなり、送料込みで5000円以下で買うことができる。

https://ja.aliexpress.com/item/4000971508364.html

このスマートウォッチの中にはESP32と呼ばれるArduino系列のマイコンが入っており、Arduino IDEというエディタを利用し、プログラミングし自分好みのスマートウォッチを作成することができる。


# 3.スマートウォッチを使えるようにするまで
デフォルトで書き込まれているプログラムで時計表示はできるが、中国時間で表示されている。
そのため、日本時刻で表示するためには、中にあるプログラム(スケッチ)を書き換える必要がある。



付属品には、micro-BタイプのUSBが接続されており、USBをPCにつなぐだけで基本的に認識される。


3-1.セットアップ作業
以下サイトを参考に、arduino IDEでコードを書くためのセットアップを行った。

https://blog.osakana.net/archives/10194





# 4.チューニング
デフォルトの時計向けスケッチである「SimpleWatch.ino」では、画面を消していても4時間ほどで充電が切れてしまった。
そこで、内臓RTCを利用した簡易時計スケッチの「RTC.ino」と、電源ボタンでスリープするスケッチの「WakeupFromPEKKey.ino」等を利用し、以下画面が表示できるスマートウォッチを作成した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702737/1f625239-5a39-a82d-3072-80d25a193c48.png)

以下githubにて作成したスケッチ公開を公開しました。参考程度にご利用ください。

https://github.com/ken089914/T-watch_onlyWatch/blob/main/WakeupFormPEKKey_202210051702.ino



# 5.結果
こちらのスケッチでは、画面を消していると12時間ほどで電池が切れた。前回制作したスマートウォッチの約3倍電池持ちがよくなった。
電源ボタンをオフした際に、deep_sleepに移行したことが功を奏したのではないかと考える。


# 6.参考サイト
1:OSAKANA TAROのメモ帳様サイト
T-Watchのセットアップ時に参考にさせていただきました。

https://blog.osakana.net/archives/10194


NTPで時刻を取得するスケッチを参考にさせていただきました。

https://wak-tech.com/archives/833


deep_sleepについて調べた際、参考にさせていただきました。

https://lang-ship.com/blog/work/esp32-deep-sleep/
rqtのプラグインが読み込めない時の修復

# 1. "rqt"と入力すると大量のエラーが出た

* 使用していない ワークスペースからプラグインがないと怒られる。
    * 下記の様に画面は出るがメニューは何も選べず…
    

    ![画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/2d880653-398d-0fe3-82dd-f6865d39bb15.png)


# 2. 解決策
* (再インストールはいらないと思いますが…)
    * 必要があれば、"sudo apt purge ros-<お使いのROS２>-rqt*"で削除
    * 再インストール

* rqtが起動する状態で以下のフォルダを確認します。

```ターミナル:コマンド入力

cd ~/.config/

MS-7B86:~/.config$ ls
@omniverse             evolution                 monitors.xml~
Code                   geany                     nautilus
FreeCAD                gedit                     omniverse
Google                 glib-2.0                  omniverse-launcher
Ignition               gnome-initial-setup-done  pip
Qt                     gnome-session             pulse
QtProject              goa-1.0                   remoteit
QtProject.conf         google                    ristretto
　　　　　　　　　　　　~~(中略)~~
eog                    monitors.xml

```
* 原因は”QtProject.conf”の中身が存在しないパスを参照していました。
    * 各々対処は異なる場合があります。ご了承ください。
    * このファイルが前回の起動画面を記憶している模様

```ターミナル:コマンド入力

cd ~/.config/

MS-7B86:~/.config$ mv QtProject.conf QtProject.bak


```
* 手直し後にrqtをターミナルより実行します。

# 3. 直りました！

![kaiketsu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/1d0a1375-f0fd-472e-39b0-a141cc6b74b4.png)

**社内(個人）向けの簡単なtipsでした。**
* 色々不具合が出て手直ししていると、英語圏や中華圏で情報がないので、メモしました。
経営戦略と事業戦略

# 経営戦略の手法
### ベストプラクティス分析
他社の同様な事例を```徹底的に研究し、それらの中から最も優れた事例（ベストプラクティス）を見つけ出す```こと。

### ベンチマーキング
改善を行う際に、他社の優れた事例（前項のベストプラクティス)を```指標(ベンチマーク)```として、```自社の現状と比較検討して分析```を行う手法。

### コアコンピタンス経営
企業が行っている事業の中で、```他社より優れた技術やノウハウを持つ分野をコアコンピタンス```という。コアコンピタンス経営はここに、```経営資源を集中させ強化```することで、利益を上げていく経営手法。

### コストリーダーシップ戦略
大きなシェアを持つ```優位性を活かしてコストダウン```を図り、```さらに優位に立つ```戦略。

### 差別化戦略
他社が成し得ないような特化した```製品やサービスに注力し、シェアを確保```する戦略。

# 競争戦略と企業ポジション
### リーダ企業
その製品分野で最大のシェアを持つ企業。定期的、戦略的に新製品を投入したり、市場の維持・拡大やブランド力の強化を図り、```常に他社をリードしていく戦略```を立てる。

### チャレンジャ企業
シェアは２〜３番手。```リーダ企業の弱点や未開拓の販売地域を狙う```など、```挑戦的な戦略```をとる。
また、下位の企業の市場を取り込むことで規模を拡大していく方法もある。

### フォロワ企業
シェアが少ない企業。徹底したコストダウンを図り、```低価格競争が可能な製品を投入```しながら、リーダ企業からの```報復を招かないようリーダ企業を追随```する戦略を立てる。

### ニッチェ企業
```小さな規模の市場を寡占的に占める企業```。他者との```競合を回避```すべく、```狭い領域```に特化した製品を投入する```ニッチ（隙間)戦略```をとることで、```高い利益を維持```していく。

# 関連記事{SWOT分析、ポートフォリオ分析（ポートフォリオマネジメント)}
https://qiita.com/masatom86650860/items/3d3a01e70f90e0c65411

### バリューチェーン分析
バリューチェーン(Value Chain: 価値連鎖）とは、「製品やサービスの価値は、```製造、販売、アフターフォローまで含め、企業活動の各工程で付加される```」という考え方。
バリューチェーン分析は、製品が持つ「価値」をその製品の「機能」と機能を持たせるための「コスト」との関係として分析し、競合製品と比較する。
分析結果を基に、```顧客の視点で「必要な機能とは何か？」を追求```する手法として```バリューエンジニアリング（VE)```といい、さらに```各工程のコストを削減し価格を抑える```ことで、```機能と価格の両面から製品の価値を上げていく```。
# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
自動化に関する 3 つの失敗談とその教訓


# はじめに
自動化完成！自動化を担当していて、これほど心躍る瞬間はありません。「これで楽ができる」、「これで早く帰れる」と期待に胸を膨らませるのもつかの間、待っていたのは失敗でした。ここでは自分が体験した自動化の失敗談と教訓を紹介します。

# 運用前の失敗談（教訓：環境チェックは念入りに！）
自動化に失敗するパターンで、おそらく一番多い原因が環境問題だと思います。開発環境で完璧に仕上げて本番環境に持って行ったところ、ライブラリがないとかバージョンが違うとかで悩まされることがあります。本番環境なのでバグ出しに時間を使うこともできず、かなり焦ります。

対策としては、下記を事前に確認しておくことになります。非常に基本的ですが、結構見落としがちな点でもあります。
- 環境、ツールのバージョン
- 使用されているライブラリ
- 文字コード等

バージョンに関して、開発環境と本番環境で揃えておくことは原則です。しかし、新しいバージョンがリリースされると、ついつい使ってみたくなります。「開発環境だからちょっとお試し」のように使ってしまって本番環境と差分が出ないよう、細心の注意を払うことが重要です。

またライブラリも問題になることが多いです。例えば Python の場合、便利なライブラリがあるためついつい使ってしまいます。ところが本番環境では、セキュリティ上の理由から追加のライブラリはインストール不可という場合もあり、標準パッケージしか使えない環境もあります。その際には、標準パッケージだけを使うように開発時から想定しておくことも必要です。

最後の文字コードに関して、最近は Unicode で文字化けはあまりありませんが、問題になるのは改行コードです。CR, LF, CR+LF といった問題は、現在でも発生します。個人的な失敗例として、ログを外部システムに REST で POST する際に、json フォーマットに書き直す自動化でこの問題に遭遇しました。ログの改行コードを json で使える \\\\n に置き換えていたのですが、システムごとにログの改行コードが違い、json の validation エラーになってうまく自動化できていませんでした。

また上記のような場合に備え、そうした事態に対処できるよう、あらかじめデバッグログを出力するようにしておくなど、事前にデバッグコードを仕込んでおくことも重要です。本番環境ではデバッグの時間が取れないため、事前の準備がとても大切になります。

**教訓**
- バージョン、ライブラリ、文字コードなど、環境差分には細心の注意を！
- 本番環境で焦らないよう、あらかじめデバッグを想定しておく！


# 運用開始時の失敗談（教訓：フェイルセーフを考慮する！）
なんとか問題なく運用を始めても、想定通りに使ってもらえないことで発生する問題があります。自分では最高に使いやすい自動化をしたつもりが、パラメータに何を入れたら良いのかわからないという問い合わせを受けたり、想定外のパターンで使われてエラーになるということもあります。

対策として、下記をあらかじめ想定しておくことが大切です
- 誰がどのように使うのか
- 想定外のパターンには何が考えられるか

自動化の目的はさまざまですが、おそらく自分が使うだけではなく、新人や不慣れな方でも作業できるようにすることが目的という場合も多いと思います。その場合は使いやすい自動化を心がけましょう。CLI ではなく、ブラウザなどのフロントエンドを被せて使いやすくするというのも重要です。また自分では json でパラメータを指定する想定が、Excel にして欲しいという要望をあとから言われることもあります。その場合は、初めから Excel で自動化を設計しておいた方がはるかに楽です。

また想定外の使い方は常に想定しておく必要があります。想定外の使い方をしても止まらない設計にする、いわゆるフェイルセーフ (fail-safe) を考慮しておくことで、安定した自動化が可能になります。考えられるパターンは無限にありますが、主なものとしては下記が挙げられます。
- パラメータの間違い（範囲外、数字の代わりに文字を入れる、「11 月 31 日」といったあり得ない日付を入れる、など）
- 自動化対象の間違い（本来と異なる対象が選択されたなど）

**教訓**
- 利用者と利用方法をあらかじめ想定しておく
- 想定外のパターンでも止まらないための foolproof を考慮した設計にする



# 運用後の失敗談（教訓：誰でも継続して開発できる環境を！）
自動化が成功し、これによって楽ができると思いきや、逆に仕事が増えるパターンもあります。追加の機能を依頼されたり、新しいパターンをリクエストされたり。共同開発のはずが、結局自分だけで抱え込むことになってしまっては大変です。

対策として下記が考えられます
- 開発の当初から、できるだけ読みやすい誰でも拡張できるような設計にする
- 開発環境やツールを明確にしておく
- あらかじめ共同作業を想定しておく

共同開発ができない原因として、まずコードが理解できないと言う点があります。開発の際、コメントを入れておくことで、そうしたことはだいぶ回避できます。初めは自分だけわかれば良いと思ってコメントを入れておかず、後になってからコメントを追記するのは大変です。初めから他の人も開発できるよう、コメントを入れておくよう心がけておくことが大切です。

また開発環境やツールを明確にしておくことも重要です。特定の環境下でないとビルドできないといった状態では、永続的に自分が開発を続けることになり、仕事が減りません。コードの説明に加えて開発環境の明確化も重要です。

複数人で開発するようになると、コードの管理も重要になってきます。Git レポジトリなどは、あらかじめ用意しておくと後で楽に運用ができます。また人によって書き方がバラバラにならないよう、書き方のルールも明確にしておくと後で読みやすくなります。Python でいえば PEP8 にどこまで準拠するのかといったルール決めも必要かもしれません。

**教訓**
- コードへのコメントは忘れないように
- 他のメンバーでも開発できるよう開発環境を明確に
- Git 等によるコード管理やコーディングルールを明確に


# まとめ
なかなか思うように行かない自動化も、最初の準備やプランニングをすることで、とてもスムーズに進むようになります。しっかりとしたプランで自動化をして、楽しい年末年始をお過ごしください。
Falco Ruleを紹介するシリーズ - Private Repository Becoming Public

本シリーズでは、ランタイム脅威検知のデファクトスタンダードである<a href=https://falco.org/ target=new>Falco</a>の検知Ruleを、１つの記事で１つ簡単に紹介していきます。
ランタイムセキュリティやFalco自体の概要を知りたい方は<a href=https://sysdig.jp/blog/intro-runtime-security-falco/ target=new>こちらのブログ記事</a>をご参照ください。
今回ご紹介する検知Ruleは<b>「Private Repository Becoming Public」</b>です。
# Rule記述
```
- rule: Private Repository Becoming Public
  desc: Detect changing the visibility of a repository to public
  condition: github.type=repository and github.action=publicized
  output: A repository went from private to public (repository=%github.repo repo_owner=%github.owner org=%github.org user=%github.user) 
  priority: CRITICAL
  source: github
```
# Rule概要
<a href="https://github.com/falcosecurity/plugins/tree/master/plugins/github" target=new>GitHub Plugin for Falco</a>をインストールすることで使用可能になるルールです。
本ルールは、プライベートリポジトリが「パブリック」に変更されたことを検知します。
会社のコードが入った公開リポジトリを持つことは、ドアのない家を持つようなものです。
そのため、リポジトリの可視性を「パブリック」に変更しようとする試みは、「クリティカル」な優先順位で処理されるべきです。
Falcoを使ったGitHubのセキュリティ確保については、<a href=https://sysdig.jp/blog/dropbox-breach-falco-plugin/>「Falco GitHubプラグインでDropboxの情報漏洩に対応する」</a>のブログ記事もご参照ください。

# Condition（条件）
`github.type=repository and`
GitHubのメッセージタイプが repository で、

`github.action=publicized`
GitHubのアクションが publicized （公開された）の場合

# Output（出力）
リポジトリがプライベートからパブリックに変更されました

`%github.repo`
リポジトリ名

`%github.owner`
リポジトリのオーナー名

`%github.org`
リポジトリが所属する組織名

`%github.user`
イベントをトリガーしたユーザー名
AWS Lambda + Translate で翻訳機能使ってみた！


*この記事はawsハンズオンビギナーズをやってみて復習として作成しています

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Serverless-1-2022-reg-event.html?trk=aws_introduction_page

今回は、Lambdaをテスト実行してその結果を英訳できるところまでをやります。

## 1 Lambda関数の作成

以下の画面から「関数の作成」ボタンをクリックします。

![スクリーンショット 2022-11-20 15.46.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/a3aec48b-ffb2-c6ec-24fb-e142114865ae.png)

~設定項目~
1,任意の関数名を入力
2,ランタイムの設定(今回はpython3.7にしました)
3,アーキテクチャは「x86_64」を選択

![スクリーンショット 2022-11-20 16.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/b1381c79-3d93-156d-1e2a-ec1f40daa82a.png)

Lambdaのサービスロールを付与します

~設定項目~
1,「基本的なLambdaアクセス権限で新しいロールを作成」を選択すればOK

![スクリーンショット 2022-11-20 16.00.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/79ebde6f-53b6-fc9e-d81f-5712fd1ee369.png)

## 2 Lambdaの関数(コード)の編集

LambdaでAWS Translateを呼び出すようにコードを編集します。

以下のリンクから

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/translate.html#Translate.Client.translate_text

以下のスクショの選択部分をコピーしておきます

![スクリーンショット 2022-11-20 17.08.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/8f305c61-9aee-fde2-07df-94da43540457.png)


![スクリーンショット 2022-11-20 16.03.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/376c9bb4-e262-466e-6f2d-22c2984a16b9.png)

Lambdaのコードの編集画面にコピペします。

コピペ後にコードの編集をします。詳細は動画をみてください。
めんどくさい方用にコードを添付しておきます。

```

import json
import boto3

translate = boto3.client('translate')

def lambda_handler(event, context):
    
    input_text = '英語できるようになりたいね'
        
    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode='ja',
        TargetLanguageCode='en'
    )
    
    output_text = response.get('TranslatedText')
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        })
    }

```

上記をそのままLambdaの関数の編集画面に設定していただければすぐにできると思います。
input_textの部分は自由に変えてみてください。

これでLambdaは完成ですが、このLambda自体にTranslateを実行する権限自体がないので権限を付与していきます。

## 3 LambdaにTranslateの実行権限を付与

IAMのロール一覧の画面から検索でLambda関数作成時に自動生成されたサービスロールを見つけます。

![スクリーンショット 2022-11-21 13.28.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/d26ea173-80fe-13e8-7756-e58814a1a250.png)

こちらのロールにTranslateの権限をつけていきます。
今回は学習用ですのでフルの権限をつけちゃいます。

![スクリーンショット 2022-11-21 13.34.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/1e60c922-0fa0-fa10-a756-901997a554c9.png)

## 4 テストしてみる

テストイベントを設定後「テスト」をクリック

![スクリーンショット 2022-11-21 13.41.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/1c27dc19-5c9d-f417-9194-d5234b7004d6.png)


英訳されました。

![スクリーンショット 2022-11-21 13.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/a00a5098-604e-381a-fe2d-da8e0174f34c.png)

お疲れ様でした。
OutSystemsでのSQLコンポーネントを使うときのコツ

OutSystemsでのSQLコンポーネントを使うときのコツ

OutSystemsでのSQLコンポーネントで使用するSQL文の書き方で
テーブル名を { } で囲むというのが地味にめんどくさいので、もっと簡単にできないかと色々試してみた。

OutSystemsでのSQLコンポーネントで使用SQL文だと

Select * from Table1 Where Table.Flg=True Order by Table.ID

みたいに書くときに

テーブル名を { } で囲まないとならないというルールにより

Select * from {Table1} Where {Table1}.Flg=True Order by {Table1}.ID

こうやってテーブル名を {Table1} と書かないとならないので地味にめんどくさい。


これは、使用するテーブルが一個であれば、まだメンドクサイだけで済むんだけど
テーブルを複数使うとなるとクソメンドクサイに変わるのね。

Table1, Table2, Table3 を使う場合、こんなかんじ。 

Select * from {Table1} 
  inner join  {Table2} on  {Table1}.ID = {Table2}.RefID 
  inner join  {Table3} on  {Table1}.ID = {Table3}.RefID 
  Where {Table1}.Flg=True 
  Order by {Table1}.ID, {Table2}.ID, {Table3}.ID

いちいち、テーブル名を { } で囲むのがねぇ…。

これを改善するにはテーブルの別名を付けることで解決する。

Select * from 
  {Table1} t1 
  inner join {Table2} t2 on  t1.ID = t2.RefID 
  inner join {Table3} t3 on  t1.ID = t3.RefID 
  Where t1.Flg=True 
  Order by t1.ID, t2.ID, t3.ID

Table1 を t1 という別名に、 Table2 を t2、 Table3 を t3 と名前をつけることで
その後のテーブルの参照がすべて別名で指定できるのが良い。

そのためOutSystemsでのSQLコンポーネントで使用するSQL文が格段に書きやすくなる。
テーブル名に { } を付けるっていう縛りが最初に別名を付けるだけで済む。


短縮型の別名だとわかりにくいというのであれば
こんな風にしてみるのもいいかもと思う。

Select * from {Table1} _Table1 
  inner join  {Table2} _Table2 on  _Table1.ID = _Table2.RefID 
  inner join  {Table3} _Table3 on  _Table1.ID = _Table3.RefID 
  Where _Table1.Flg=True 
  Order by _Table1.ID, _Table2.ID, _Table3.ID

これも、ちょっと面倒か…
普通に短縮形の別名を付けるほうが楽かもな…と思う。
UnrealEngine TArrayの使い方

# はじめに
UEでよく使われる動的配列(TArray)を使う上で気をつけたほうがいいことなどについて話します。

# 要素を追加するときの再配置を意識しよう
要素を一つだけ追加した場合、メモリに確保される要素数はいくつでしょうか？
```cpp
TArray<int32> Array;

Array.Emplace(1);

UE_LOG(LogTemp, Log, TEXT("size: %d"), Array.Max());
```
正解は４です。

```cpp
TArray<int32> Array;

Array.Emplace(1);
Array.Emplace(1);
Array.Emplace(1);
Array.Emplace(1);
Array.Emplace(1);

UE_LOG(LogTemp, Log, TEXT("size: %d"), Array.Max());
```
５つ追加したらどうなるでしょうか？２２でした。
ちょうど５個目の要素を追加した時に再配置が発生し、領域が拡張されます。

再配置は比較的重たい処理なのでなるべく減らすことを考えましょう。
もし追加する要素数が決まっているのであれば、事前にReserve()で予約してあげると１回ですみます。

また、配列の中の要素のポインタを変数などに保持して使うのも危険です。
なぜなら再配置がおきるとアドレスが変わってしまうためです。

```cpp
TArray<FString> Array = { TEXT("Test0") };

// 危険！
FString* Text = &Array[0];

Array.Emplace(TEXT("Test1"));
Array.Emplace(TEXT("Test2"));
Array.Emplace(TEXT("Test3"));
Array.Emplace(TEXT("Test4"));	// 再配置がおきてTextポインタは無効な領域を指してしまいます
```

# 要素の追加はAddよりEmplace？
UEのドキュメントを見ると「Emplace は常に Add より効率的です」と書かれているのでEmplaceを使いましょう。
https://docs.unrealengine.com/4.26/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/TArrays/

なんで？
```cpp
FORCEINLINE SizeType Add(const ElementType& Item)
{
	CheckAddress(&Item);
	return Emplace(Item);
}
```
Addの関数を見ると中でEmplaceを呼んでます。最適化されたらどっちも一緒な気がします。
なのでどっちでもいいんじゃないかな？

# forループ中で要素を削除するのは危険
```cpp
TArray<int32> Array = { 0, 1, 2, 3, 4 };

for(int32 i : Array)
{
	if (i == 2)
	{
        // 危険！
		Array.Remove(i);
	}
}
```

foreachループは内部でイテレータを持っています。イテレーターは今処理している要素のindexをもっています。
今、イテレーターのindexは2で、2の要素を指している状態です。
この状態で2の要素を削除するとどうなるでしょうか？

|index|内容|
|----|----|
|0|0|
|1|1|
|2|3|
|3|4|

イテレーター(index:2)の次の要素は3ではなく4になります。
３をすっとばしてしまいますね。

なので特定の要素を削除したいときはRemoveAllを使いましょう。
```cpp
Array.RemoveAll([](int32 i) { return i == 2; });
```

# 削除するときのコストも考えよう

配列の途中にある要素を削除すると後ろの要素が前に詰められます。これにはオーバーヘッドが発生してしまいます。
もし配列の順番に意味がないのであれば以下の関数を使うようにしましょう。

- RemoveAllSwap
- RemoveAtSwap
- RemoveSingleSwap
- RemoveSwap

これらの関数は順序が保証されない代わりにオーバーヘッドを回避することができます。
調べてないけど、空いたところにお尻の要素を詰めてるんだと思います。

# 便利な機能紹介

- FindByPredicate
- ContainsByPredicate
特定の条件に合致するものを検索
```cpp
int32* item = Array.FindByPredicate([](int32 i) { return i == 2; });
```

- AddUnique
要素がなければ追加

- TMap::FindOrAdd
配列じゃないけど、検索時に無かったら追加してくれるので存在しなかった場合の処理を書かなくていい。

# 最後に
便利な配列ですが、内部でどういう挙動をしているか把握して無駄のないコードが書けるといいですね。
for文で手続き的にガリガリ書くのもいいですが、RemoveAllSwapやFindByPredicateなどでラムダ式を使えばもっとスッキリ書けて読みやすいコードになると思います。
【Golang】1 バイトデータのビットローテーション【左循環シフト】

> Go 言語（以下 Golang）で、1 バイトのデータを[左シフト](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97#%E7%AE%97%E8%A1%93%E3%82%B7%E3%83%95%E3%83%88)させたのち、右側末尾に[ビット・ローテーション](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97#(%E3%82%AD%E3%83%A3%E3%83%AA%E3%83%BC%E3%81%AA%E3%81%97)%E3%83%AD%E3%83%BC%E3%83%86%E3%83%BC%E3%83%88)させたい。いわゆる、ひとつの[循環シフト](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97#%E8%AB%96%E7%90%86%E3%82%B7%E3%83%95%E3%83%88)。

普通にビットシフトすると溢れたビットは消えてしまうのです。

```go
func main() {
	v := uint8(0b11110000)
	w := v << 1 // 1 ビットの左シフト
	fmt.Printf("%08b\n", v)
	fmt.Printf("%08b\n", w)
}
// Output:
// 11110000
// 11100000
```

つまり、こういうことがしたいのです。

```diff
  # Before
- 0b11110000
  # After
+ 0b11100001
```

「（`bytes` にローテーションってないのかしら）」と、[「golang 1バイト 左シフト ローテーション」でググる](https://www.google.com/search?q=golang+1%E3%83%90%E3%82%A4%E3%83%88+%E5%B7%A6%E3%82%B7%E3%83%95%E3%83%88+%E3%83%AD%E3%83%BC%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3&nirf=golang+1%E3%83%93%E3%83%83%E3%83%88+%E5%B7%A6%E3%82%B7%E3%83%95%E3%83%88+%E3%83%AD%E3%83%BC%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)も、タイトルからドンピシャの記事がヒットしなかった（開かないとわからない）記事ばかりだったため、自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. [math/bits](https://pkg.go.dev/math/bits) パッケージの [RotateLeft 系](https://pkg.go.dev/math/bits#RotateLeft)の関数を使う。
1. RotateLeft 関数の種類<sub><sup>（`x` = データ、`k` = シフトしたいビット数・マイナス値は右ローテーション）</sup></sub>
    1. [`RotateLeft(x uint, k int) uint`](https://pkg.go.dev/math/bits#RotateLeft)
    1. [`RotateLeft8(x uint8, K int) uint8`](https://pkg.go.dev/math/bits#RotateLeft8)
    1. [`RotateLeft16(x uint16, k int) uint16`](https://pkg.go.dev/math/bits#RotateLeft16)
    1. [`RotateLeft32(x uint32, k int) uint32`](https://pkg.go.dev/math/bits#RotateLeft32)
    1. [`RotateLeft64(x uint64, k int) uint64`](https://pkg.go.dev/math/bits#RotateLeft64)
1. マスター、動くものをくれ。

    ```go
    package main
    
    import (
    	"fmt"
    	"math/bits"
    )
    
    func Example() {
    	fmt.Printf("%08b\n", 0b00001111) // --> 15
    	fmt.Printf("%08b\n", bits.RotateLeft8(15, 1))  // 左シフト
    	fmt.Printf("%08b\n", bits.RotateLeft8(15, -1)) // 右シフト
    
    	// Output:
    	// 00001111
    	// 00011110
    	// 10000111
    }
    ```
- [オンラインで動作を見る](https://go.dev/play/p/gYETc49zAWQ) @ Go Playground
【Python】threadingによる並列処理(非同期処理)

マルチプロセスとの使い分け
 - CPU負荷の高い処理（CPU bound）は、マルチプロセス（multiprocessing）
 - I/Oの待ち時間が大きい処理（I/O bound、いわゆる非同期処理）は、マルチスレッド（threading）

## 並列処理コード
ParallelProcessingに並列処理を行いたい関数とスレッドを跨ぐたびに引数を更新する関数を入れる。
functionとupdateでそれらを記述する。

```python:sample_threading.py
from threading import Timer
import time

# 並列処理を行うClass
class ParallelProcessing(Timer):
  def __init__(self, interval, function, update, args={}, kwargs={}):
    # Timerクラスのメンバー関数を呼び出して展開している
    Timer.__init__(self, interval, self.run, args, kwargs)
    self.thread = None
    self.function = function
    self.update = update
    self.function.counter = 0

  def run(self):
    self.thread = Timer(self.interval, self.run)
    self.thread.start()
    self.function(**self.args, **self.kwargs)
    self.args = self.update(**self.args)

  def cancel(self):
    if self.thread is not None:
      self.thread.cancel()
      self.thread.join()
      del self.thread

# 並列に処理を行いたい関数
def function(**kwargs):
    function.counter += 1
    print(kwargs['key'], function.counter)

# 引数を各スレッドで更新する
def update(**kwargs):
    updated_kwargs = {}
    for key, val in kwargs.items():
        if key == 'key':
            val = val + 'Hello'
            updated_kwargs[key] = val
    return updated_kwargs

if __name__=='__main__':
    process = ParallelProcessing(0.5, function, update, {"key":"Hello"})
    # 並列処理 開始
    process.start()
    time.sleep(10)
    # 並列処理 停止
    process.cancel()
```


### 同じファイルに非同期で同時にアクセスしたい場合
ロックを取得してからファイルに書き込むことで、同時アクセスを制御する。
```Python
import threading

lock = threading.Lock()

def write_to_file(data):
    with lock:
        with open('file.txt', 'a') as file:
            file.write(data)
for i in range(1000):
    thread1 = threading.Thread(target=write_to_file, args=('aaa'))
    thread1.start()
thread1.join()
```

## まとめ
theadingを用いた並列処理をやってみた。覚書として、記事にまとめておく。
リクエストからレスポンスまでのプロセスを制御する、"HttpKernel"

[Symfony Component Advent Calendar 2022](https://qiita.com/advent-calendar/2022/symfony-component)の4日目の記事です。

## 最初に
[Symfony](https://symfony.com)はPHPのフレームワークのひとつです。しかし、公式サイトの説明文には

> Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
  （SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。）

と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。

今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。

※記事内ではautoloadのインポートは省略します。


## リクエストからレスポンスまでのプロセスを制御する、"HttpKernel"

[HttpKernel](https://symfony.com/doc/current/components/http_kernel.html)は、リクエストからレスポンスまでのプロセスを制御するコンポーネントです。

### インストール

```shell
composer require symfony/http-kernel
```

### 主なフロー

SymfonyではHttpKernelを使って次のようなフローでリクエストを処理してレスポンスを返しています。

1. リクエストを受け取り、リクエストオブジェクトを作る
2. `kernel.request`イベント発火
3. どのプログラムを実行するか決める
4. `kernel.controller`イベント発火
5. プログラムを実行し、レスポンスオブジェクトを作る
5.1. `kernel.view`イベント発火
6. `kernel.response`イベント発火
6. レスポンスオブジェクトから、レスポンスを送る
7. 終了する
8. `kernel.terminate`イベント発火
8.1. `kernel.exception`イベント発火 

要所でイベントを発火し、該当箇所で必要な処理を実行するようになっています。
たとえば、`kernel.request`では、ルーティング設定を作成する処理が実行されます。

### 各イベントの目的

それぞれの箇所でのイベントの目的は次のようになっています。そろぞれの箇所で処理を追加したり、データを加工する必要がある場合は、該当のイベントをサブスクライブ・リッスンすることで可能となります。

| イベント | 目的 | クラス |
|---|---|---|
| kernel.request | リクエストオブジェクトに追加情報をつける | RequestEvent |
| kernel.controller | コントローラー実行前の初期処理 | ControllerEvent |
| kernel.view | もし、実行結果がレスポンスオブジェクトではない場合、結果からレスポンスオブジェクトを生成する | ViewEvent |
| kernel.response | 出力前にレスポンスオブジェクトを加工する | ResponseEvent |
| kernel.terminate | レスポンス出力後に必要な**重い**後処理を実行する | TerminateEvent |
| kernel.exception | 例外発生後の処理とレスポンスオブジェクトの作成 | ExceptionEvent |


## まとめ

今回はHTTPのプロセス制御を行う`HttpKernel`の紹介でした。この`HttpKernl`と、ここまでに出てきた`HttpFoundation`, `Routing`, `EventDispatcher`を使い、SymfonyではHTTPのリクエストからレスポンスを返す仕組みを提供しています。
dockerログイン時エラー対処法 Error saving credentials: error storing credentials - err: exit status 1, out: `Post "http://ipc/registry/credstore-updated": open \\.\pipe\dockerBackendApiServer: The system cannot find the file specified.`

```
Error saving credentials: error storing credentials - err: exit status 1, out: `Post "http://ipc/registry/credstore-updated": open \\.\pipe\dockerBackendApiServer: The system cannot find the file specified.`
```
の解消方法

# 発生要件

以下コマンド実行時

```
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
```

# 解消方法

/home/user/.docker/config.jsonの```"credsStore": "desktop.exe"```を削除して再実行する

## 修正前

```
{
        "auths": {
                "https://index.docker.io/v1/": {}
        },
        "credsStore": "desktop.exe"
}
```

## 修正後

```
{
        "auths": {
                "https://index.docker.io/v1/": {}
        }
}
```

ちなみに正常実行後は以下のようにconfig.jsonに認証情報が埋め込まれる。credsStore..部分が悪さして、それができなかった模様

```
{
        "auths": {
                "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com": {
                        "auth": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                },
                "https://index.docker.io/v1/": {}
        }
}
```

# 参考にさせていただいた情報

https://www.capybara-engineer.com/entry/2021/12/24/114535
エラーは違うが同じ操作で解消