OmniAICreator/Qiita-1.07M huggingface dataset:
frameset を iframe に置き換える方法

# 背景
frameset は HTML5 で廃止予定のため、iframe に置き換える必要がある。
frameset では フレームの枠を掴んでサイズ変更できるが、
iframe ではサイズ変更できないのでJavaScriptでサイズ変更できるようにする。

# 実装方法
以下のように実装する。

```html
<!DOCTYPE html>
<html>
<style>
body {
  margin: 0;
}
hr {
  cursor: n-resize;
  height: 2px;
  margin-top: 1px;
  margin-bottom: 5px;
}
#overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, .3);
  transition: .3s linear;
  display: none;
  cursor: n-resize;
}
iframe {
  width: 100%;
  border: none;
}
</style>
<body>
<div id="overlay"></div>
<iframe id="frame1" src="https://en.wikipedia.org/wiki/IFrame" style="height:70vh"></iframe>
<hr>
<iframe id="frame2" src="https://en.wikipedia.org/wiki/IFrame" style="height:25vh"></iframe>

<script>
//Make the DIV element draggagle:
dragElement(document.querySelector("body > hr"));

function dragElement(elmnt) {
  elmnt.onmousedown = dragMouseDown;

  function dragMouseDown() {
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
    document.getElementById("overlay").style.display = "block";
  }

  function elementDrag(e) {
    // set the element's new position:
    document.getElementById("frame1").style.height = (e.clientY - 15) + "px";
    document.getElementById("frame2").style.height = window.innerHeight - e.clientY - 10 + "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
    document.getElementById("overlay").style.display = "none";
  }
}
</script>

</body>
</html>
```

- 動作サンプル
https://jsfiddle.net/89rjmqcy/

- 参考URL
https://www.w3schools.com/howto/howto_js_draggable.asp
[06] subprocessの代替パッケージ「sh」を使ってみる ... Git 操作をする

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

# はじめに

一般的に Python で Linux コマンドを使う場合は `subprocess` を使うこと多い.
が、標準パッケージでは無いものの subprocess の代替である「`sh`」(`amoffat/sh`) も便利である.[^1]

個人的な考えではあるが、「sh[^2]」は標準パッケージでは無いので、職場などで使い込むと
他者の迷惑になり兼ねない。しかし、適度に使う分には `subprocess` よりも速く実装できて
好都合なので書き残しておく.

ここでは **Git Contrib という機能を使って Git 操作を実現** する例を記す.
(ただし、Read Only 系の操作に絞る)

なお、ほとんど理解できていないが、Git が Contrib という名称で CLI を提供しており、
どうやら「sh」がこの Contrib を使えるようである.

この実装方法であれば <font color="blue">シェルスクリプトに近い感覚で実装できる</font>ので、
subprocess や <font color="red">GitPython</font> よりも速く実装できるのではないかと思う.[^3]



# セットアップ

pip 等で `sh` をインストールする.
詳細は本項末尾の「[参考情報](#参考情報)」に記した.


# 使用例

ここでは次の Git操作の実装例を記す.

・git remote -v
・git branch -a
・git log --since '2021/08/01' --until '2021/08/05'

なお、[公式ドキュメント](https://amoffat.github.io/sh/sections/contrib.html?highlight=git) を参考にすること.


## git remote -v

もしも「unicode().decode('utf-8', 'ignore') raising UnicodeEncodeError ...」が
発生した場合は、後述の「[UnicodeEncodeError 対策](#unicodeencodeerror-対策)」を参照すること.

```python
import sh
from sh.contrib import git

if __name__ == '__main__':
  for line in git.remote('-v'):
    print(line.rstrip())
```

　

## git branch -a

もしも「unicode().decode('utf-8', 'ignore') raising UnicodeEncodeError ...」が
発生した場合は、後述の「[UnicodeEncodeError 対策](#unicodeencodeerror-対策)」を参照すること.

```python
import sh
from sh.contrib import git

if __name__ == '__main__':
  for line in git.branch('-a'):
    print(line.rstrip())
```

　

## git log --since '2021/08/01' --until '2021/08/05'

ログ精査などに便利である.

もしも「unicode().decode('utf-8', 'ignore') raising UnicodeEncodeError ...」が
発生した場合は、後述の「[UnicodeEncodeError 対策](#unicodeencodeerror-対策)」を参照すること.

```python
import sh
from sh.contrib import git

if __name__ == '__main__':
  for line in git.log('--since', '2021/08/01','--until', '2021/08/05'):
    print(line.rstrip())

```


# 補足

## UnicodeEncodeError 対策

次の一文を追加してやれば良い.

```diff
  for line in git.log('--since', '2021/08/05','--until', '2021/08/06'):
+   line = line if not isinstance(line, bytes) else line.decode('utf-8', "ignore")
    print(line.rstrip())
```

　

# 参考情報

|項目|URL|一言|
|:--|:--|:--|
|Pypi sh|https://pypi.org/project/sh/||
|公式ドキュメント - トップページ|https://amoffat.github.io/sh/||
|公式ドキュメント - API逆引き|https://amoffat.github.io/sh/reference.html||
|チュートリアル|https://amoffat.github.io/sh/tutorials|ここで実現したい機能を検索しながら使うことが多い|
|もた日記|https://wonderwall.hatenablog.com/entry/2017/07/30/083000||
|git contribを使う|https://qiita.com/soranoba/items/eef8fdf4334394e52c92|


# 検討環境

```bash
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
```

　

以上

[^1]: 私は職場で別の方が使用していて知った
[^2]: パッケージ名が「sh」だと検索し辛い..
[^3]: Git 操作はシェルスクリプトが良いとは思っている
CodeSignal - rotateImageにチャレンジ

コーディングしなさすぎてコーディングを忘れたエンジニアがコーディングを思い出すためにコーティングします。
今回は、アメリカのコーデイング練習サイトCodeSignalの問題「rotateImage」を解いていきます。
サイトによると、この問題はAmazon、Microsoft、Appleの面接で出されたことがあるようです。

##問題
画像を表したn×nの2Dの行列が配列として与えられるので、それを時計回りに90度回転して出力する関数を書きます。
たとえば以下であれば、

```Java
a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]
```

出力はこうなります。

```Java
rotateImage(a) =
    [[7, 4, 1],
     [8, 5, 2],
     [9, 6, 3]]
```

制約：
1 ≤ a.length ≤ 100
⇨配列の長さは1以上100以下
a[i].length = a.length
⇨画像の縦横の要素数は同じ
1 ≤ a[i][j] ≤ 10^4
⇨配列の中の値は1以上10000以下

##解説・考え方
とりあえず上のサンプルを見てみると、90度回転後は、
・1が上段右に移動
・2が中段右に移動
・3が下段右に移動
・4が上段中に移動
・・・
というように順番に並べ替えれば解けることに気づきます。
そこで、ループを2つ回して回転前の配列から順番に値を取り出し、もう一つ作った同じ要素数の2次元配列に順番を入れ替えてセットしていくことにしました。

Javaで書くとこんな感じです。

```Java
int[][] rotateImage(int[][] a) {
    int arraySize = a.length;
    int[][] answer = new int[arraySize][arraySize]; 
    for(int i=0; i<arraySize; i++){
        for(int j=0; j<arraySize; j++){
            //　answer[0][2] = a[0][0]
            //　answer[1][2] = a[0][1]
            //　answer[2][2] = a[0][2]
            //　answer[0][1] = a[1][0]
            //　answer[1][1] = a[1][1]
            //　and so on
            answer[j][arraySize - 1 - i] = a[i][j];
            
        }
    }
    return answer;
}

```
コードの説明
まず答え用にanswerという、お題と同じ要素数の2次元配列を用意しています。
その後、2つのループで2次元配列の値を先頭からチェックしています。
ループの中で回転前の値を、answerの然るべき位置に一つづつセットしています。


##感想
単純なアプローチしか思いつかず、またも他の回答者のコードに圧倒されることとなりました。

他の回答者をみると、PythonやJavascriptでたった1行で書けているものがありました。
あまり読み解けてないのですが、reverseやlambdaを使って配列をソートしているようでした。
幅優先探索で実装するアルゴリズムまとめ by Python

幅優先探索は、深さ優先探索と並べて紹介されることが多いですが、アルゴリズムの中で出会う場面は深さ優先探索と比べると少ない印象です。



###グラフ探索
N個の頂点とM個の辺からなる有向グラフGにおいて、始点sから各頂点に接続可能かを判定する。

```Python:GraphSearch.py
# グラフ探索：幅優先探索

# アルゴリズム定義
def BFS(G, s):
    N = len(G)
    
    seen = [False for i in range(N)]
    todo = []
    
    seen[s] = True
    todo.append(s)
    
    while todo:
        v = todo[0]
        del todo[0]
        
        for x in range(len(G[v])):
            if seen[G[v][x]]:
                continue
            seen[G[v][x]] = True
            todo.append(G[v][x])
    
    return seen

# 入力受取            
N, M = map(int, input().split())

# グラフ生成
G = [[] for i in range(N)]
for j in range(M):
    a, b = map(int, input().split())
    G[a].append(b)

# アルゴリズム実行
BFS(G, 0)

# 入力
# 6 8
# 0 1
# 0 4
# 0 5
# 1 2
# 2 4
# 2 5
# 3 4
# 3 5

# 出力
# [True, True, True, False, True, True]
```

###最短路
N個の頂点とM個の辺からなるグラフGにおいて、始点sから各頂点への最短路を求める。

```Python:ShortestPath.py
# 最短経路アルゴリズム
# 計算量：O(|V|+|E|)

# アルゴリズム定義
def BFS(G, s):
    N = len(G)
    dist = [-1 for i in range(N)]
    que = []
    
    dist[0] = 0
    que.append(0)
    
    while len(que) != 0:
        v = que[0]
        que.pop(0)
        
        for x in range(len(G[v])):
            if dist[G[v][x]] != -1:
                continue
            dist[G[v][x]] = dist[v]+1
            que.append(G[v][x])
    
    return dist

# 入力受取
N, M = map(int, input().split())

# グラフ生成
G = [[]for i in range(N)]
for i in range(M):
    a, b = map(int, input().split())
    G[a].append(b)
    G[b].append(a)

# アルゴリズム実行    
dist = BFS(G, 0)

# 結果出力
for v in range(N):
    print(v, ":", dist[v])

# 入力
# 9 13
# 0 1
# 0 2
# 0 4
# 1 3
# 1 4
# 1 8
# 2 5
# 3 7
# 3 8
# 4 8
# 5 6
# 5 8
# 6 7

# 出力
# 0 : 0
# 1 : 1
# 2 : 1
# 3 : 2
# 4 : 1
# 5 : 2
# 6 : 3
# 7 : 3
# 8 : 2
```
Kotlin/JSで作ったReact HooksをTypeScriptから使う

## 概要

Kotlin/JSでReactのカスタムフックを作成し、TypeScript用の型定義ファイルを生成します。
とりあえずTypeScriptから使えた程度の出来でまだ詳細は把握しきれておらず、実用性は皆無です。
Kotlin側のコードはKotlin/JSで直接Reactを使う場合でも同じく有効です。

下記の記事から分かる通り現時点で(2021/08/03)IRバックエンドはalphaなので、慎重に利用してください。
https://kotlinlang.org/docs/components-stability.html

## Kotlin/JSを使う

Kotlin/JSのコードから型定義ファイル(.d.ts)を生成するためには、`@JsExport`を適用する必要があります。
しかし、プリミティブしかJavaScriptから取り扱うことができないため、いくら型定義ファイルを生成しても、JavaScriptから高度なライブラリを操作することはかなり厳しいです。

そこで、Ktolin/JSでラップすることで間接的に表現することができます。
本記事ではその例としてReact HooksとKotlin coroutinesの組み合わせを挙げています。

## コード

### Kotlin

``` build.gradle.kts
plugins {
    kotlin("js") version "1.5.30-M1"
}

group = "com.uramnoil"
version = "0.1.0"

repositories {
    mavenCentral()
}

val kotlinVersion = "1.5.21"
val reactVersion = "17.0.2"

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1")
    implementation("org.jetbrains.kotlin-wrappers:kotlin-react:17.0.2-pre.224-kotlin-1.5.21")
    implementation(peerNpm("react", reactVersion))}

kotlin {
    js(IR) {
        binaries.library()
        browser()
    }
}
```

``` hooks.kt
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import react.useState

val flow = MutableStateFlow(0)

@JsExport
fun useHoge(): String {
    var hoge by useState(flow.value)

    useEffectOnce {
        GlobalScope.launch { // NOTE: Dangerous API
            flow.collect {
                hoge = it
            }
        }
    }

    return hoge.toString()
}

// Flow操作用
@JsExport
fun increment() {
    flow.value++
}
```

### TypeScript

``` package.json
{
    "dependencies": {
        "project-root-name": "link:/folder/to/ProjectRoot/build/js/packages/project-root-name"
    }
}
```

``` App.tsx
import "./App.css";
import { increment, useHoge } from "kotlin-react-library-sample";

function App() {
  const hoge = useHoge();

  return (
    <div className="App">
      {hoge}
      <button onClick={() => increment()}>hoge</button>
    </div>
  );
}

export default App;
```

## サンプル

https://github.com/UramnOIL/KotlinReactLibrarySample

![画面収録.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271071/c7f64060-276a-d877-aa41-efa0396a2201.gif)

普通に動きます。

## まとめ

ViewModelを扱うReact Hooksを作っておけば、Kotlin/Multiplatformでロジックを共通化していてもTypeScriptでフロントエンドを作れるようになります。

もう少し調査してみて記事を書いてみたいと思います。
1周目　railsチュートリアル第3章

#目次
[1.はじめに](#1-はじめに)
[2.大まかな流れ](#2-大まかな流れ)
[3.復習メモ](#3-復習メモ)
[4.感想](#4-感想)
[5.おわりに](#5-おわりに)

#1. はじめに
前回の記事

https://qiita.com/ak-matsu/items/e8a6fa4f654b9d82994b

3章を途中まで読み進めていたが、
AWSのcloud9の容量がいっぱいになり不要分の削除や
無料増量分のボリューム増設などで学習開始が遅れた。

さて、第3章は「ほぼ性的なページの作成」であり、第6版の無料枠はここまでである。
一応rails５．１(第４版）は無料で１章〜14章まで見れるが、改版があるので差分はこちらを参照したほうがいいです。

https://speakerdeck.com/yasslab/railstutorial-4e-6e-diff

#2. 大まかな流れ

- sampleアプリの作成
- 静的ページの説明
    - 省略コマンド
    - キャメルケースとスネークケース
    - controllerでhome,helpアクション作成
    - ルーティングの変更
 -　テストの作成
    -　RED,Green,Refactor
   
#3. 復習メモ

キャメルケースでコントローラーを作成すると
キャメルケース：単語の頭文字を大文字にしてつなぎ合わせること

```
$ rails generate controller StaticPages home help
```

スネークケースでコントローラーファイルが作成される
スネークケース：小文字で作成され単語間にアンダースコアができる
static_pages_controller.rb　のコントローラーが生成される。

#### rails で使える短縮形

|完全なコマンド|短縮形|
|-|-|
|$ rails server	|$ rails s|
|$ rails console|$ rails c
|$ rails generate|$ rails g|
|$ rails test|$ rails t|
|$ bundle install|$ bundle|

今回のテストはコントローラーテストである。
- RED
テストが失敗したときの表現
正直この段階でエラー表示の見方がまだ安定していない。

- Green
テストが成功したときの表現
パスする

- Refactor
プログラムの動きは書き換えずにソースコードを書き換える
結果は変えず、中身を簡潔にして書き換えること。

埋め込みRubyを使うことにより重複を防ぐことができる。
home.html.erb

erb内で<% ... %> と　<%= ... %>　があるが、
<%　は単純にコードを実行するだけで何も表示されない
<%= は中の変数や計算式の結果を<b>挿入</b>して実行結果を表示する。

#4. 感想
無料枠は3章までである。
まとめ方を変えたほうがいいかもしれない、章ごとではなく、セクションごとに変えたほうが良さそう。
しかも次回の4章からは有料のため、
より一層理解度を上げてまとめないとついていけなさそう。

明日辺りに動画とwebテキスト+αのスタイルで購入してみます。

#5. おわりに
次回は4章

https://qiita.com/ak-matsu/items/c655a73c236b18835837
Rails Strong Parameterとは

# Strong Parameterとは
Rails には、```ストロングパラメーター（Strong Parameter）```という、***ユーザーから送信されるデータを制限する機能***があります。
この仕組みを使うことで、***安全では無いデータの登録・更新を防いでくれます。***

# ストロングパラメータの書き方
1. ***基本構文***

```user_controller.rb
private
def user_params
  params.require(:キー(モデル名)).permit(:カラム名１,：カラム名２,・・・).merge(カラム名: 入力データ)
end
```

```user_controller.rb

class UsersController < ApplicationController
  # (中略)

  private 

    def user_params
      params.require(:user).permit(:name, :email, :password,:password_confirmation)
    end
end

```
***メソッド名には[ モデル名_params ]***とするのが一般的です。

# reqireメソッドとparmitメソッド
基本的には、require と permit の使い方さえわかっておけば大丈夫です。

① ```require```: ***受け取る値のキーを設定***
② ```permit```: ***許可するカラムを設定***

上の場合はパラメーターの ***:userというキーの中の:name, :email,:password,:password_confirmationだけを許可する設定***にしました。

つまりパラメーターとしての ***:name, :email, :password,:password_confirmation4つだけデータの作成・更新を許可する*** といった内容になっています。

***ストロングパラメーターを使わずに、そのままユーザーから送られてきた値を使ってデータを作ったり、更新しようとすると、ユーザーに書き換えられたくない値まで書き換えられてしまう***という問題が起きてしまいます。

他にも```privateメソッド```と```mergeメソッド```もあります。

# ストロングパラメータの呼び出し方

丸投げパターン

```user_controller.rb
def create
    User.create(user_params)
  end

```
ストロングパラメータに全てお任せパターンです。」


# 資料

https://railstutorial.jp/chapters/sign_up?version=7.0#sec-the_form_html
Ubuntuでシリアルデバッグツールのtinyserial、CuteCom、Serial Monitorを比較

シリアル通信の解析とデバッグには、いくつツールがあります。今回は、tinyserial、CuteCom、Serial Monitorを使って見て比較します。

# tinyserial

## インストール
[carloscn/tinyserial](https://github.com/carloscn/tinyserial)の[ソース](https://github.com/carloscn/tinyserial/releases)からコンパイルします。

## 起動

```
tinyserial-1.3.0/build$ ./tinyserial
```

## シリアルポートを開く
[ASCII]モードで受信したデータが文字化けになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/f9fc9838-0e70-4279-5a0a-572d87e57785.png)

[Hex]モードに変更しても、同じ文字化けになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/73aede2d-20ce-4d55-1046-d2cd01455bf4.png)

## 結論
シリアルポートから出力している通信データが見えなかった。

# CuteCom

## インストール
```
sudo apt update
sudo apt install cutecom
```

## 起動
インストールしたアプリから起動します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/cc40844f-81ee-bf50-3c39-b8de7f8d34a3.png)


## シリアルポートを開く
[ASCII]モードで受信したデータがバイト毎に16進数で表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/75b23c94-cbea-7615-7a29-8f3ac68dc137.png)

[Hex output]モードをチャックすると、16進数で表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/56f155a6-a262-6c33-03a4-b25e585b21a7.png)

## 結論
シリアルポートから出力している通信データが[Hex output]モードで見えます。


# Serial Monitor

## インストール
[Serial Monitor](https://ioninja.com/plugins/serial-monitor.html)から[Tibbo Device Monitor on Linux](https://ioninja.com/doc/kb/tdevmon_linux_installation.html)をインストールします。

## 起動
インストールしたIO Ninjaから起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/b5acaf26-ffa5-7b34-364c-ed599b9aa13e.png)

[File]-[New Session]-[Serial Monitor]を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/9a534a58-8bc0-e97b-3265-bd535c1654cf.png)

解析したいシリアルポートの監視を開始

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/3f89a267-1332-e048-61f1-e87f712e2538.png)

シリアルポートを使用するアプリケーションを起動すると、通信データが見えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/044dddeb-d126-54a3-acf3-4cec281ac011.png)

## 結論
Serial Monitorは、別デバッグしたいアプリケーションのシリアルポート通信データを解析可能です。
シリアルポートの開く、閉じる、設定変更の監視も可能です。
Serial Monitorは、有料ソフトですが、7日間体験ライセンスを使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/a187555b-e9ea-a88a-8339-ce6408bfddc1.png)
#PowerApps AddColumns の出力件数に気をつけましょう

Power Apps の AddColumns 関数は、参照しているテーブルに対して、独自の列を関数を用いて生成することができます。
データを元に合計値を自動計算したり、別のデータソースからLookupしたりなど、とても有用な関数です。
ですが、このAddColumns関数で生成したテーブルの件数には、実は制限があります。

# 実は公式のDocsにもサラッと書いてある。

[Microsoft Docs | Power Apps の AddColumns、DropColumns、RenameColumns、および ShowColumns 関数](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-table-shaping)

公式のDocsにも実はこんなふうに書いてあったりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/71037ed1-f3a3-2288-b323-70b5008de007.png)

そうなんです、AddColumns関数で出力される件数は、500件まで
正確には、データ行の制限に指定された件数までしか取得できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/b480de96-5cba-4551-50b2-0d9c6754423f.png)

AddColumns 関数の先がその件数を超えていたとしても、その件数までしか出力できません。

# 実際に試してみましょう

5000件近いデータが入ったSharePoint リストを用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/e6245a5b-a215-c3ed-8ea5-c5464815f022.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/c1a11fad-c24b-1b7f-e54e-8c412548b05e.png)

## AddColumns関数で年代別の列を追加する

データテーブルのItems に以下の関数を入力してみます。
※年代別の列を追加し、２０代でフィルター

```
Filter(
    AddColumns(
        testdata5000,
        "価格",Value(Mid(balance,1,Len(balance)-1)),
        "年代",If(
            And(age>=0,age<10),"0代",
            And(age>=10,age<20),"10代",
            And(age>=20,age<30),"20代",
            And(age>=30,age<40),"30代",
            And(age>=40,age<50),"40代",
            And(age>=50,age<60),"50代",
            And(age>=60,age<70),"60代",
            And(age>=70,age<80),"70代",
            And(age>=80,age<90),"80代",
            And(age>=90,age<100),"90代"
        )
),年代="20代")
```

そうすると以下のようなデータテーブルが生成できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/50e9d668-7b4b-8cf7-9c72-60453dd4c97f.png)

データ件数を調査してみると、このようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/3e6e3df0-fbd7-0466-810f-bfb8bc5e7af1.png)

AddColumns での件数は244件
それに対して、SharePointでの件数では2405件

全然違いますね！
しかも、不思議なことにAddColumnsの件数は500件にも満たしていません。

## 年齢ごとに更に分析してみる

２０代の各年齢ごとに何件あるかそれぞれ比較してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/35566b49-76a3-a650-021f-b91f6a4c4001.png)

各年齢毎で調べてみると AddColumnsで生成したテーブルには２０件前後のデータしか存在しません。

# AddColumnsの列生成の対象レコード

AddColumnsで列を生成する際は、対象のテーブルのうち最初の500件のみを使って、そのデータから列の生成処理を行っているようです。
なので、AddColumnsを使って列生成を行うためには、対象のデータソースが500件以内である必要があります。

データソースの指定時はFilter関数などをある程度集約した状態で実施しておくなどの工夫をする必要があります。

# まとめ

AddColumnsは本当にとても便利な関数です。
ただし、使用するにはとても慎重に行う必要があるとも言えます。
対象のデータがどういうもので、どれだけの件数があるのかなど、逐一確認するようにしておくと良いでしょう。
BootstrapVueにてBootstrapが上手く機能してない時の原因と解決方法

いいですよねぇBootstrapって！少しの行数であんなにすごく綺麗なレイアウトが組めるんですから！
さらにVue.jsも素晴らしい！プログレッシブだから、開発規模に合わせて柔軟に対応できる！

そんなふたつが合わさったものが、記事を読んでいる人が使っている<b>BootstrapVue</b>です。

さて、そんなBootstrapVueなんですが、私、ここ最近になって新しいプロジェクトに入れることにしたんです、bootstrapVueを。

そしたらなんとね、<b>上手く機能してくれないんですよ</b>！！
具体的には、b-buttonのblockが効かなかったり、navbarの一部が不自然だったり、、、ぱっと見のレイアウトとか機能は問題なく動いてるんですけどね...😔

仕方なく検索しても、それっぽい記事がなかったので、今回は中々ないであろうこの問題について、紹介しますね。

# 環境

- dockerを使用(今回は階層とかは関係ないのでパス)
- macOS 11.5.1
- VueCLI 4.5.11
- Vue 2.6.14
- yarn 1.22.10

# 結論：解決方法

先に結論から言いますと、

一度削除して、bootstrap<b>4.5.3</b>とbootstrapVueを入れ直す！

ってな感じです。そのために、以下のコマンドを使います。

```terminal:ターミナル(bootstrapとbootstrap-vueの削除)
$ yarn remove bootstrap bootstrap-vue
```


```terminal:ターミナル(bootstrap4.5.3とbootstrap-vueの追加)
$ yarn add bootstrap@4.5.3 bootstrap-vue
```

以上でうまい具合に動作すると思います。

# 原因

私が頭を抱えたこの問題の原因は、<b>Bootstrapのバージョン</b>にありました。

ここで、package.jsonをご覧ください。

```json:package.json
"bootstrap": "^5.0.2",
"bootstrap-vue": "^2.21.2",
```

ここの、bootstrapのところを見ると、"5.0.2"と書かれていますね。つまり、bootstrap5.0.2を使用していることになっているんです。

## なぜbootstrapのv5がダメなのか

※ここで、bootstrapの5.xをv5と、4.xをv4と略します。

なぜ最新であるはずのv5が、bootstrapVueになると急にダメダメちゃんになるのか。

それは、<b>互換性のなさ</b>があります。
まぁ、ここで「互換性」という言葉が正しいかは分かりませんが。

では、一体何と互換性がないというのか。
それが、<b>v4</b>なんです。

## bootstrapVueはv4で動作する

<a href="https://bootstrap-vue.org/docs">BootstrapVue | Getting Started</a>には、動作する条件が書かれています。その中に、以下の内容が書かれています。

> Bootstrap v4.3.1 is required, v4.5.3 is recommended

直訳すると、

> Bootstrap v4.3.1は必要です。v4.5.3をお勧めしますがね。

って書かれています。つまり、お勧めのバージョンは<b>4.5.3</b>なんです。

## v5とv4の大きな差異

多分この記事を見ているという人は、こういう経験をしたかと思います。

「あれ、b-buttonのblockが効かないぞ...？」
「なんでclassにml-2を書いてるのに、右側にmarginが出てこないんだ...」

そう、それが<u>v4とv5との差異</u>なんです！！
実は<a href="https://getbootstrap.com/docs/5.0/migration/#utilities">Bootstrap5 | Migrating to v5</a>を見てみると、確かにこう表示されているのです。

> Breaking Renamed several utilities to use logical property names instead of directional names with the addition of RTL support:
> Renamed .ml-* and .mr-* to .ms-* and .me-* .
> Renamed .pl-* and .pr-* to .ps-* and .pe-* .

これを完璧に訳することはできませんが、ニュアンス的に、
「.ml-* とか.mr-* を、ms-* とかme-* に変更」
みたいなことが書かれてると思います。つまり、v4でのmlとかが使えないんですね...

# 最後に

まぁ、こういう事態に陥っている方はあまりいないとは思いますが、困ってる人のため、素人なりに即席ながら記録してみました。知識不足なところがあると思いますが、ご了承ください🙏
[05] subprocessの代替パッケージ「sh」を使ってみる ... sudo をパスワード自動入力で使う

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

# はじめに

一般的に Python で Linux コマンドを使う場合は `subprocess` を使うこと多い.
が、標準パッケージでは無いものの subprocess の代替である「`sh`」(`amoffat/sh`) も便利である.[^1]

個人的な考えではあるが、「sh[^2]」は標準パッケージでは無いので、職場などで使い込むと
他者の迷惑になり兼ねない。しかし、適度に使う分には `subprocess` よりも速く実装できて
好都合なので書き残しておく.


[前項](https://qiita.com/robozushi10/items/4b613de3fd84776ff776)では `sh.contrib.sudo` を使ったが、パスワード入力が毎回発生してしまう.
そこで、本項では「**<font color="blue">「sh」で sudo を使いつつパスワードを自動入力する方法</font>**」を記す.

この実装方法であれば <font color="blue">シェルスクリプトに近い感覚で実装できる</font>ので、
subprocess よりも速く実装できるのではないかと思う.


# セットアップ

pip 等で `sh` をインストールする.
詳細は本項末尾の「[参考情報](#参考情報)」に記した.


# 使用例

## 005.py ... パスワードを自動入力する

[公式ドキュメント](https://amoffat.github.io/sh/sections/sudo.html?highlight=sudo#sh-sudo)の `sh.sudo.bake` による実装方法にする.

なお、`bake` は `焼き固める` の意味のようである.


### コード

ここではパスワード🈲が「`PASSWORD`」であるものとする.

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys; sys.dont_write_bytecode = True
import os
import traceback
import sh

if __name__ == '__main__':
  # password must end in a newline
  my_password = "PASSWORD\n" ##🈲
  
  # -S says "get the password from stdin"
  my_sudo = sh.sudo.bake("-S", _in=my_password)

  T = '{0}/work/'.format(os.environ['HOME'])
  for d in my_sudo.find(T, '-maxdepth', '4', '-type', 'd', '-name', '.git'):
    try:
      absp = os.path.abspath(d).rstrip()
      print(absp)
    except:
      traceback.print_exc(file=sys.stdout)

```
　
### 実行結果


```bash
/home/foo/work/wiki/02_software/xx/.git
/home/foo/work/wiki/02_software/git-lfs/.git
/home/foo/work/wiki/02_software/git-lfs2/.git
/home/foo/work/wiki/02_software/xx2/.git
/home/foo/work/LOCAL_GITLAB/fluentd/.git
/home/foo/work/fluentd/.git
```


# 参考情報

|項目|URL|一言|
|:--|:--|:--|
|Pypi sh|https://pypi.org/project/sh/||
|公式ドキュメント - トップページ|https://amoffat.github.io/sh/||
|公式ドキュメント - API逆引き|https://amoffat.github.io/sh/reference.html||
|チュートリアル|https://amoffat.github.io/sh/tutorials|ここで実現したい機能を検索しながら使うことが多い|
|もた日記|https://wonderwall.hatenablog.com/entry/2017/07/30/083000||


# 検討環境

```bash
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
```

　

以上

[^1]: 私は職場で別の方が使用していて知った
[^2]: パッケージ名が「sh」だと検索し辛い..
GitLFS用のLambdaの.NETCoreをアップデートする

# S3 の GitLFS サーバ の Lambda関数 の .NETcore をアップデートする

## 経緯

AWS の Lambda にて .NETcore2.1 のサポートが 2021/09/20 で終了するとの通知が来たので、
[以前構築したGitLFSサーバのLambda関数](https://qiita.com/c0ba1t_coke/items/94ed3a62ab34078a1f92)をアップデートすることに

- CloudFormationの変更セットを使って、Lambda関数だけアップデートできるか検証する

## 手順

### ファイル準備

新しいyamlファイルと鍵Zipファイルをアップする

```yaml
SigningLambda:
    Type: AWS::Lambda::Function
    Properties:
        Code:
            S3Bucket: !Sub 'gitlfs-test'
            S3Key: Estranged.Lfs.Hosting.Lambda.zip
        Description: Generates S3 signed URLs for Git LFS
        FunctionName: !Ref AWS::StackName
        Handler: Estranged.Lfs.Hosting.Lambda::Estranged.Lfs.Hosting.Lambda.LambdaEntryPoint::FunctionHandlerAsync
        MemorySize: 512
        Role: !GetAtt SigningLambdaRole.Arn
        Runtime: dotnetcore3.1
```

S3key の部分と Runtime の部分を変える

S3 にアップロードして、オブジェクトURLをコピペしておく

### CloudFormation 変更スタックとして実行

- 変更セット作成

```
$ aws cloudformation create-change-set --stack-name gitlfs-server --change-set-name gitlfs-change-set --template-url 'https://gitlfs-test.s3.ap-northeast-1.amazonaws.com/git-lfs_new.yaml' --change-set-name gitlfs-change-set --parameters file://[path/to/params.json] --capabilities CAPABILITY_IAM

arn:aws:cloudformation:ap-northeast-1:571357558873:changeSet/gitlfs-change-set/79bed005-8343-42e0-924e-558f398812d1
arn:aws:cloudformation:ap-northeast-1:571357558873:stack/gitlfs-server/23a6e0c0-f467-11eb-82c8-0a9dd4300739
```

- 変更セットの実行

```
$ aws cloudformation execute-change-set --change-set-name gitlfs-changeset --stack-name gitlfs-server
```

### 確認

コンソールで確認

- CloudFormation Stack

スタックのステータスで`UPDATE_COMPLETE`になってたらOK

- Lambda

ランタイム設定が `.NET Core 3.1` になってたらOK

- S3

バケットが変わらずそのままならOK

大丈夫そう！

### Git LFS動作確認

```sh
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        binaries/photos/Z6_02_01.jpg

nothing added to commit but untracked files present (use "git add" to track)

$ git add .
$ git commit -m "バイナリファイル追加"
[master de08335] バイナリファイル追加
 1 file changed, 3 insertions(+)
 create mode 100644 binaries/photos/Z6_02_01.jpg

$ git push
Enumerating objects: 8, done.1/1), 15 MB | 0 B/s                                                                                               
Counting objects: 100% (8/8), done.
Delta compression using up to 2 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 549 bytes | 549.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/lfs-test
   f59078c..de08335  master -> master
```

- S3, CodeCommit 確認

→ちゃんとS3に実体だけUPされてる！
【競プロ典型90問】001の解説（python）

## 概要
[競プロ典型90問](https://atcoder.jp/contests/typical90)の解説記事です。
解説の画像を見ても分からない（~~理解力が足りない~~）ことが多々あったので、後で解き直した際に確認できるようまとめました。

※順次、全ての問題の解説記事を挙げていく予定です。

## [問題001-Yokan Party](https://atcoder.jp/contests/typical90/tasks/typical90_a)

### 問題概要
長さLのようかんをK+1個に切り分けた時のピースの中で最も小さいピースの最大値を求める。
ただし、切り分ける場所は、N箇所のいずれか(A1 ~ AN)で指定されている。

### 制約

```math

1 <= K <= N <= 100000 \\

0 < A1 < A2 < ・・・ < AN < L <= 10^9

```

### 解き方

全ての切り分け方を求めてから計算する方法は、
N個の切れ目からK個選ぶパターン、すなわちnCk通りを調べることになり、NG。

そこで今回は、
1. X(cm)以上の長さでようかんを切り分けられるかを判定する
2. 1~Lまでで上記1の判定を通るものの最大値を求める
といった流れで実装していく。

１に関して、ようかんの端から順に切れ目を見ていき、X（cm）以上になったら
ようかんのピースを+1（個）するといった形で実装できる。
この時の計算量は、O(N)。

2に関して、1~Lに対して、二分探索を用いることによって、
判定を満たす最大値を求められる。（二分探索に関しては[こちら](https://qiita.com/wihan23/items/82798e1a838141977cbd)）
この時の計算量は、O（logL）。

判定の計算量がNで、判定する際の計算量がlogLのため、
合計でO(NlogL)。これは約10の6乗になるので、十分に間に合う。

![参考画像](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/001.jpg "公式解説画像")

引用元：[競プロ典型90問 Github](https://github.com/E869120/kyopro_educational_90)

### 実装

```python:answer.py

# 入力の受け取り
N, L = map(int, input().split())
K = int(input())

# 先頭に0、末尾にLを追加することで切れ目の差を求めやすくする
A = [0]+list(map(int, input().split()))
A.append(L)

# 判定するメソッド。cntで切れ目の差の合計がx以上になった時の個数を計測。lで切れ目の差を加算していく。（x以上になったらlはリセット）
def check(x):
  cnt = 0
  l = 0
  for i in range(N+1):
    l += A[i+1] - A[i]
    if l >= x:
      cnt += 1
      l = 0
  return cnt >= K+1

# 二分探索のテンプレ
ng = L
ok = -1

while ng - ok > 1:
  mid = (ok + ng) // 2
  if check(mid):
    ok = mid
  else:
    ng = mid

# 二分探索により、okにcheckがtrueになる、最大値が入っているので、okを出力
print(ok)

```

## 最後に
問題の解説を読んでも他の人のコードを見てもさっぱり分からないという方の
力に少しでもなれれば幸いです。
~~（自分は最初、さっぱり分かりませんでした。）~~

ここまでお読みいただきありがとうございました。
特定のvalueが入っているkeyをオブジェクト内から取り出したいときはlodashのfindKeyを使おう

# 公式

https://lodash.com/docs/4.17.15#findKey

# サンプル

```javascript
const obj = {
  hoge: 'fuga',
  foo: 'bar',
  hogehoge: 'fuga'
}

// キーを会得する
const key = _.findKey(obj,function(value, key) {
  return value === 'fuga'
});
// => findKeyには'hoge'が渡される

// おまけ: valueを会得する
obj[key]
// => 'fuga'
```

# 動作説明

```javascript
_.findKey(object, [predicate=_.identity])
```

### 引数
- `object (Object)`: 検索したいオブジェクト
- `[predicate=_.identity] (Function)`: 検索するための関数を渡す、findKeyはこの関数を用いてオブジェクト内を検索する

### returnされる値
- 最初に一致した要素のキー

# 経緯
オブジェクト内で特定の値が入っているkeyを会得したいなと思い色々調べていた時に発見。最初はなんとなくこういう機能はJSに入っているだろうと思っていたけどまさか入っていないとは、、、結構ニッチな需要なのかな？

# findKeyの内部コード

https://github.com/lodash/lodash/blob/2f79053d7bc7c9c9561a30dda202b3dcd2b72b90/findKey.js

なるほどねー、`Object.keys`でkeyを配列にしたあと`Array.prototype.some`でvalueを会得、predicateで渡した関数を回して最初に合格した値を返すという訳ですね。蓋を開けるとシンプルだけど面白いなー。でもfindKey内でpredicateに第三引数としてobject渡しているのはなんでだろう？
[04] subprocessの代替パッケージ「sh」を使ってみる ... sudo を使う

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

# はじめに

一般的に Python で Linux コマンドを使う場合は `subprocess` を使うこと多い.
が、標準パッケージでは無いものの subprocess の代替である「`sh`」(`amoffat/sh`) も便利である.[^1]

個人的な考えではあるが、「sh[^2]」は標準パッケージでは無いので、職場などで使い込むと
他者の迷惑になり兼ねない。しかし、適度に使う分には `subprocess` よりも速く実装できて
好都合なので書き残しておく.


[前項](https://qiita.com/robozushi10/items/dd9f1e72860ae727f77f)では `sh.find` を使ったが、探索権限が無いディレクトリにアクセスすると例外が発生してしまう.
そこで、本項では「**<font color="blue">「sh」で sudo の使用する方法</font>**」を記す.

この実装方法であれば <font color="blue">シェルスクリプトに近い感覚で実装できる</font>ので、
subprocess よりも速く実装できるのではないかと思う.


# セットアップ

pip 等で `sh` をインストールする.
詳細は本項末尾の「[参考情報](#参考情報)」に記した.


# 使用例

## 004.py ... パスワードを毎回入力する

[公式ドキュメント](https://amoffat.github.io/sh/sections/sudo.html?highlight=sudo#terminal-input)の `sh.contrib.sudo` による実装方法にする.

なお、sudo のたびにパスワードを毎回入力する必要がある.

### コード

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys; sys.dont_write_bytecode = True
import os
import traceback
import sh

if __name__ == '__main__':
  T = '{0}/work/'.format(os.environ['HOME'])
  for d in sh.contrib.sudo.find(T, '-maxdepth', '4', '-type', 'd', '-name', '.git'):
    try:
      absp = os.path.abspath(d).rstrip()
      print(absp)
    except:
      traceback.print_exc(file=sys.stdout)

```
　
### 実行結果


```bash
[sudo] password for foo: 🈲🈲パスワード入力する🈲🈲
/home/foo/work/wiki/02_software/xx/.git
/home/foo/work/wiki/02_software/git-lfs/.git
/home/foo/work/wiki/02_software/git-lfs2/.git
/home/foo/work/wiki/02_software/xx2/.git
/home/foo/work/LOCAL_GITLAB/fluentd/.git
/home/foo/work/fluentd/.git
```


# 参考情報

|項目|URL|一言|
|:--|:--|:--|
|Pypi sh|https://pypi.org/project/sh/||
|公式ドキュメント - トップページ|https://amoffat.github.io/sh/||
|公式ドキュメント - API逆引き|https://amoffat.github.io/sh/reference.html||
|チュートリアル|https://amoffat.github.io/sh/tutorials|ここで実現したい機能を検索しながら使うことが多い|
|もた日記|https://wonderwall.hatenablog.com/entry/2017/07/30/083000||


# 検討環境

```bash
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
```

　

以上

[^1]: 私は職場で別の方が使用していて知った
[^2]: パッケージ名が「sh」だと検索し辛い..
state-of-frontend

以下でランキング入っているサービス
https://tsh.io/state-of-frontend/

□Hosting
Amazon Web Services
Netlify
Google Cloud Platform
Microsoft Azure
Vercel
Heroku

□CI tool
GitLab CI
GitHub Actions
Jenkins
Circle CI
Bitbucket Pipelines
Travis CI
Azure DevOps/Pipelines


□Container Management
Docker
Kubernetes
Amazon ECS/EKS
Google Kubernetes Engine
Azure Containers

□SSG
Gatsby
Next.js
Nuxt
Jekyll
Hugo
Vuepress
Docusaurus
Gitbook
Eleventy
Web上の画像をファイルに残さずOpenCV用に取り込む

#やりたかったこと
WEB上の画像をローカルに保存することなく、OpenCV用の形式(ndarray)に変換する関数が欲しかったので作った。


#開発環境
- Windows 10 Home 21H1 64bit
- Python 3.9.4

#コード
```Python:imread_web
import cv2
import requests
import tempfile
import os

def imread_web(url):
    # 画像をリクエストする
    res = requests.get(url)
    img = None
    # Tempfileを作成して即読み込む
    fp = tempfile.NamedTemporaryFile(dir='./', delete=False)
    fp.write(res.content)
    fp.close()
    img = cv2.imread(fp.name)
    os.remove(fp.name)
    return img

# 使用イメージ
img = imread_web('https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png')
cv2.imshow('Googleロゴ', img)
```

#メモ
`tempfile.NamedTemporaryFile()`は閉じたら自動で削除される一時的な空FileObjectを生成してくれる。
これを利用しカレントフォルダに一時ファイルを生成、WEBから取得した画像を書き込んで即座に読み込んだあと削除している(結局一瞬ローカルにファイルは生成される)。
本来with句を使ってファイルを閉じる処理と削除する処理は省略出来るのだが、Windows環境のみ書き込んだあと手動で閉じない限り読み込めない(=`cv2.imread()`の返り値がNoneになる)仕様が存在するために冗長な記述となっている。

>[tempfile --- 一時ファイルやディレクトリの作成 — Python 3.9.4 ドキュメント](https://docs.python.org/ja/3.9/library/tempfile.html#tempfile.NamedTemporaryFile)
*tempfile.NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True)*
この関数は、ファイルシステム上でファイルが可視の名前を持つことが保証される (Unix においてはディレクトリエントリが unlink されない) 点以外は TemporaryFile() と正確に同じことを行います。 その名前は、返されたファイル様オブジェクトの name 属性から取得することができます。 名前付き一時ファイルがまだ開かれている間にこの名前を使って再度ファイルを開くことができるかどうかは、プラットフォームによって異なります (Unix 上では可能ですが、 Windows NT 以降ではできません)。

#参考
[Webから引っ張ってきた画像をOpenCVで処理して表示する話 - EnsekiTT Blog](https://ensekitt.hatenablog.com/entry/2018/06/25/200000)
[Windows10でのPythonの一時ファイルtempfile.NamedTemporaryFileへのアクセス　～　Windowsではいったん閉じないと駄目 - 日常メモ](https://financial-it-engineer.hatenablog.com/entry/2020/04/30/140144)
デジタルトランスフォーメーション 入門

DX 入門講座の受講の備忘録です。 
DX だからと言って特別な手法はなく、古来から活用されている QC 手法などで応用可能なので、
得意なフレームワークを活用して DX を進められればと思います。

#概要
DX を実現するために必要な要素は、4つ。 

1. 企業文化のデジタル化 
+ クラウド等の最新技術の活用 
    + 自社内のデジタル機器/システムの最新化 
+ Innovation 
    + 自社既存事業の半歩先でデジタル技術を活用 
+ Rennovation
    + より良い デジタル体験をお客様に提供する
   
# DX を推進するには

+ DX の統括担当を選定する
    + IT 部門が担当するか、あるいは、営業部門が担当するか選択する
+ DX に必要なスキル
    + 実務スキル
        + Agile 開発スキル
            + 個人との対話を重視
            + ドキュメントよりも動作するソフトウェアを重視
            + 短いフィードバック
        + 円滑な情報共有（PM）

+ DX に必要な改革の進め方
※ DX ならではの手法というより、QC 手法の課題解決、あるいは問題解決ストーリーを活用すれば良い。
    + 社長直属の IT担当者を置く
    + 社内システムを図示する
    + 課題/DX によるメリットを整理する
    + Cloud 技術を活用する / プロセスを簡潔化する
    + 標準化の推進


# DX 計画
+ 3年後の将来ビジョンを選定する
    + そのためにもまずは DX に興味を持つ、好奇心を持つことが大切
Java超基本文法

##はじめに
就職活動を行なっている中で、企業様からJavaの基礎を使って解く問題が課題で出されまして、触ったことはありませんが、Javaの基礎学習を始めます。

よろしくお願いします。

##文字の出力
System.out.print()で、()の中身を出力できます。
文字列を出力させる場合はダブルクオーテーションが必要です。

ちなみに「println」ですが、「l」はエルです。
私は「i」だと思いました。
ちなみにセミコロンは必須で文末に必要です。

```java
System.out.println("Hello World");
// => Hello World
```

文字列同士の足し算（結合)ができます。計算するときと同じように「+」を使って結合します。

```java
System.out.println("Hello" + "新しい私");
System.out.println("3" + "5");

// => Hello新しい私
// => 35
``` 


##数値の出力
数値の場合は、ダブルクオーテーションが必要ありません。
()内で「+」や「-」の記号を使って計算結果を出力することもできます。

```java
System.out.println(5);
System.out.println(2 + 1);
System.out.println(7 - 5);

// => 5
// => 7
// => 3
```

そのほかの計算は普段使用している記号とは少し違います。
掛け算は「*」を、割り算は「/」を、割り算をしてあまりだけを表示させるときは「%」を使用します。

```java
System.out.println(5 * 2);
System.out.println(10 / 5);
System.out.println(7 % 2);

// => 10
// => 2
// => 1
```


##変数の定義と値の代入
変数を定義するときに、なんのデータをいれる変数なのか、データ型を宣言しなければなりません。
文字列を入れる変数であればはじめに「String]
数値を入れる変数であればはじめに「int」
数値の中でも小数を扱う場合は「double」
と宣言します。

値の代入は他の言語同様「=」で代入します。

```java
String name;
name = "Taro"

int number1;
number1 = 7;

double number2;
number2 = 3.14;

System.out.println(name);
System.out.println(number1);
System.out.println(number2);

// => Taro
// => 7
// => 3.14
```

変数の宣言と代入は下記のように一緒にすることもできます。

```java
String name = "Taro";
int number1 = 7;
double number2 = 3.14;
```
##変数の上書き
すでに値が入っている変数に、さらに値を代入すると後者の値に上書きされます。
上書きするときはデータ型の宣言をしません。

```java
String name = "山田";
System.out.println(name);
// => 山田

name = "田中";
System.out.println(name);
// => 田中
```
##自己代入と省略
ある数値の変数に数字を足してその変数に代入することを自己代入と言います。
下記のような形です。

```java
int n = 5;
System.out.println(n);
// => 5

n = n + 3;
System.out.println(n);
// => 8
```

さらにこの自己代入の省略が下記のとおりです。
（上記の例の変数定義の部分は割愛しています。）

```java
n += 3;
System.out.println(n);
// => 8
```

さらに足す（引く）数字が「1」の場合のみ、下記のように省略できます。
(変数には上記の例と同じように「5」が代入されています。

```java
n ++;
// => 6

n --;
// => 4;
```

##コメントアウト
コメントアウトは文頭に「//」をつけます。

```Java
//コメントアウト
```
[03] subprocessの代替パッケージ「sh」を使ってみる ... findコマンド

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

# はじめに

一般的に Python で Linux コマンドを使う場合は `subprocess` を使うこと多い.
が、標準パッケージでは無いものの subprocess の代替である「`sh`」(`amoffat/sh`) も便利である.[^1]

個人的な考えではあるが、「sh[^2]」は標準パッケージでは無いので、職場などで使い込むと
他者の迷惑になり兼ねない。しかし、適度に使う分には `subprocess` よりも速く実装できて
好都合なので書き残しておく.


本項では「**<font color="blue">「sh」で find コマンドする</font>**」を記す.

この実装方法であれば <font color="blue">シェルスクリプトに近い感覚で実装できる</font>ので、
subprocess よりも速く実装できるのではないかと思う.


# セットアップ

pip 等で `sh` をインストールする.
詳細は本項末尾の「[参考情報](#参考情報)」に記した.


# 使用例

下記シェルスクリプト「003.sh」相当を、パッケージ「sh」を使って Python で実装する


## 003.sh

### 処理概要

$HOME/work/. から4階層下までを対象に、「.git/」が存在するディレクトリの絶対パスを得る

### コード

```bash
#!/bin/bash
find $HOME/work -maxdepth 4 -type d -name ".git" | xargs -I@ realpath @
```

### 実行結果

```bash
/home/foo/work/wiki/02_software/xx/.git
/home/foo/work/wiki/02_software/git-lfs/.git
/home/foo/work/wiki/02_software/git-lfs2/.git
/home/foo/work/wiki/02_software/xx2/.git
/home/foo/work/LOCAL_GITLAB/fluentd/.git
/home/foo/work/fluentd/.git
```

　

## 003.py

上述のシェルスクリプトを、Python パッケージ「sh」を使って実装する.

ここでは <font color="blue">sh.find</font> を使うが、シェルスクリプトのように簡潔な記法になっており、
subprocess から置き換えるメリットがあるかと思われる.


### コード

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys; sys.dont_write_bytecode = True
import os
import traceback
import sh

if __name__ == '__main__':
  T = '{0}/work/'.format(os.environ['HOME'])
  for d in sh.find(T, '-maxdepth', '4', '-type', 'd', '-name', '.git'):
    try:
      absp = os.path.abspath(d).rstrip()
      print(absp)
    except:
      traceback.print_exc(file=sys.stdout)

```

### 実行結果

```bash
/home/foo/work/wiki/02_software/xx/.git
/home/foo/work/wiki/02_software/git-lfs/.git
/home/foo/work/wiki/02_software/git-lfs2/.git
/home/foo/work/wiki/02_software/xx2/.git
/home/foo/work/LOCAL_GITLAB/fluentd/.git
/home/foo/work/fluentd/.git
```


# 参考情報

|項目|URL|一言|
|:--|:--|:--|
|Pypi sh|https://pypi.org/project/sh/||
|公式ドキュメント - トップページ|https://amoffat.github.io/sh/||
|公式ドキュメント - API逆引き|https://amoffat.github.io/sh/reference.html||
|チュートリアル|https://amoffat.github.io/sh/tutorials|ここで実現したい機能を検索しながら使うことが多い|
|もた日記|https://wonderwall.hatenablog.com/entry/2017/07/30/083000||


# 検討環境

```bash
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
```

　

以上

[^1]: 私は職場で別の方が使用していて知った
[^2]: パッケージ名が「sh」だと検索し辛い..
PlatformIOでQT Py を動かす

Adafruit QT Pyは[Seeeduino XIAO](https://www.switch-science.com/catalog/6335/)とピン互換のボードで、
[スイッチサイエンスさん](https://www.switch-science.com/catalog/7025/)などで手に入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/565f7279-3fcb-dbcd-55b2-f14c90732db3.png)
XIAOとピン互換ですが完全互換ではないので、
PlatformIOでXIAO向けにビルドしたプロジェクトをそのまま使えるわけではありません。

```platformio.ini
[env:seeed_xiao]
platform = atmelsam
board = seeed_xiao
```
を

```platformio.ini
[env:adafruit_qt_py_m0]
platform = atmelsam
board = adafruit_qt_py_m0
```
に変更する必要があります。

また、ボードにビルトインされているLEDもNeoPixelとなっているため、
いわゆるBlinkのサンプルでのLチカはできません。

ピンは```#define PIN_NEOPIXEL         (11u)```で定義されているので、Adafruit_NeoPixelのライブラリを導入後、例えば

```blink.cpp
#include <Adafruit_NeoPixel.h>
#define NUMLED (1)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMLED, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(50);
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  strip.setPixelColor(0, 0x4f00ff); // RBG
  strip.show();
  delay(100);
  strip.setPixelColor(0, 0x107f10);
  strip.show();
  delay(900);
}

```
のようにすると紫と緑でLチカすることができます。
FAST LEDのライブラリも試してみたのですが、こちらはビルドが通りませんでした。

また、[こちら](https://learn.adafruit.com/adafruit-qt-py/pinouts)によると

>Onboard Neopixel pins
There is a very tiny NeoPixel that is connected to digital pin 11 for signal. If you would like to turn off the pixel for low power usage, set pin 12 low. By default pin 12 is set high for you by Arduino/CircuitPython

とあるので、ＬＥＤを使用する予定がなく、低消費電力で使用したい場合はPIN12をLOWにしておいたほうが良いかもしれません。
ローカルにインストールしたパッケージとライブラリの削除方法[Homebrew, Ruby(Gem)]

## この記事の目的

以下の手順通り、Rubyの開発環境構築を自動化しました。方法としましては、シェルスクリプトを用いて、Homebrewによるパッケージのインストールの段階からコードで管理するようにしました。
その際に、シェルスクリプトの冪等性を確保する為に、このスクリプトを用いた環境構築のテストを行う必要がありました。
そしてそのテストの為に、一度ローカルにあるパッケージやGemを削除しましたが、少し面倒だったので忘れないようここに記しておきます。

https://qiita.com/koki0527/items/6cbd1b0b41c9f33a69cc

## Homebrewでインストールしたパッケージを削除する

私はローカルの環境構築の自動化をテストしたかった為、出来る限りローカルを初期状態に戻す必要がありました。その為私は、**自身でインストールしたパッケージ**と、**依存関係によりインストールされたパッケージ**全てを削除しようと考えました。その方法を下に記載します。

### 一覧を表示

Homebrewでは、パッケージのことをformulaeと呼びます。以下formulaeの部分は任意のパッケージに置き換えて読んでください。

```bash
$ brew list
==> Formulae
formulae1   formula2  formula3  formula4
```

### アンインストール

```bash
$ brew uninstall formula1
$ brew uninstall formula2 formula3 # 複数一括削除も可能
```

### 依存関係の確認

```bash
$ brew deps ruby
	libyaml
	openssl@1.1
	readline
```

### インストール方法の確認

ここで言うインストール方法と言うのは、以下の2通りのことを指します。

「私自身の指示でインストールする方法」もしくは
「依存関係によりインストールされる方法」

上記の例で言うと、`ruby`は前者であり、`libyaml`や`openssl@1.1`は後者に当たります。
これを確認するの為には以下のコマンドを実行し、`"installed"`の項目を確認します。

```bash
$ brew info --json=v1 ruby
	#（前略）
    "installed": [
      {
        #(中略)
			}
			{
        "installed_as_dependency": false,
        "installed_on_request": true
      }
    ],
	#（後略）
```

`"installed_as_dependency"`が依存関係によりインストールされたもので、
 `"installed_on_request"`がユーザーの指示でインストールされたものです。

上の4つのコマンドを駆使し、追加でインストールされたパッケージを全て削除しました。

## Rubyの外部ライブラリGemを全て削除する

rubyのgemを削除する手法は2stepに分かれています。

1. インストールしたgemを削除する
2. 上位で削除できないdefault設定のgemも削除する

これら2ステップにより、ローカル内のgemを全て削除しました。

### ①　インストールしたgemを削除する

```bash
# default以外のgemを削除する
$ gem uninstall -I -a -x --user-install --force
	:

# defaultのgemが残る
$ gem list

*** LOCAL GEMS ***

benchmark (default: 0.1.0)
bigdecimal (default: 2.0.0)
	:
zlib (default: 1.1.0)

```

### ②　default設定のgemも削除する

```bash

# gemの環境設定を確認する
$ gem environment
	RubyGems Environment:
	  - INSTALLATION DIRECTORY: /Users/****/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0

# gemのdefault設定を確認する
$ cd ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
$ ls
	build_info	bundler		cache		doc		extensions	gems		specifications
$ cd specifications
$ ls
	default # このディレクトリがgemのデフォルト設定を管理する場所

# 上で確認したgemのdefault設定を削除
$ rm -rf ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/specifications/default

# defaultも含む全てのgemが削除されている
$ gem list

*** LOCAL GEMS ***

```

これによりgemを全て削除することができた。なおこの操作の後、ルートディレクトリ配下の`.rbenv`や`ruby-version`なども削除し、初期設定に近づけた。

## 参考記事

https://qiita.com/vintersnow/items/fca0be79cdc28bd2f5e4

https://rcmdnk.com/blog/2017/07/31/computer-mac-homebrew-brew-file/

https://qiita.com/katoy/items/9bcba54b88c5fc7d9aa6

https://qiita.com/KONTA2019/items/1d2fc90b5020486b0504
MaaS関連の資料リンク

# 目的
MaaS(Mobility as a Service)にかかわる資料のリンクを抽出し、全体像を把握する。

# おすすめ
★★★：特化した情報があり、わかりやすい
★★☆：特化した情報がある
★☆☆：参考になる

# 政府/省庁
## 官邸
未来投資戦略 2018
―「Society 5.0」「データ駆動型社会」への変革―  [2018-06-15]
https://www.kantei.go.jp/jp/singi/keizaisaisei/pdf/miraitousi2018_zentai.pdf

## 国土交通省
★★★ 先行モデル事業概要
https://www.mlit.go.jp/common/001293854.pdf

★★☆ 日本版MaaSの推進
https://www.mlit.go.jp/sogoseisaku/japanmaas/promotion/

★★☆ 令和2年度36事業
https://www.mlit.go.jp/sogoseisaku/japanmaas/promotion/pdf/%E4%BB%A4%E5%92%8C2%E5%B9%B4%E5%BA%A636%E4%BA%8B%E6%A5%AD.pdf

★★☆ MaaS 関連データの連携に関するガイドライン Ver. 2.0
https://www.mlit.go.jp/sogoseisaku/transport/content/001399662.pdf

★★☆ 公共交通政策
https://www.mlit.go.jp/sogoseisaku/transport/sosei_transport_tk_000117.html

★★☆ MaaS （モビリティ・アズ・ア・サービス) について ＠国土交通省
https://www.mlit.go.jp/pri/kikanshi/pdf/2018/69_1.pdf

★☆☆ 交通政策基本計画(1次)
https://www.mlit.go.jp/sogoseisaku/transport/sosei_transport_tk_000057.html

★☆☆ 交通政策基本計画(2次：2021-2025)
https://www.meti.go.jp/press/2021/05/20210528006/20210528006.html

★★☆ 交地域公共交通に関する用語解説
http://koutsu-shien-center.jp/glossary/index.html

## 総務省
★☆☆ 次世代の交通　MaaS
https://www.soumu.go.jp/menu_news/s-news/02tsushin02_04000045.html

## 自治体
★★☆ 小山市コミュニティバス　おーバス　
https://www.city.oyama.tochigi.jp/site/o-bus/234074.html

# 企業
★☆☆ モビリティ革命の実現に向けて ＠JR東日本
https://www.jreast.co.jp/eco/report/pdf_2018/p12-13.pdf


# サイト
★★★ MaaSとは MACNICA
https://www.macnica.co.jp/business/maas/columns/136215/

★☆☆ 観光型MaaSの取り組みまとめ【2020年～2021年7月】
https://ligare.news/story/tourism-0723/?doing_wp_cron=1628082187.9648079872131347656250

--
Sveltekitで抽選ツールを作ってみた

職場の朝会でファシリテーターをくじびきツール使って毎朝抽選しているのですが、
そのツールが入力項目を記憶してくれないので、
入力項目をLocalStorageに保存しておくようなくじびきツールを作ってみました :sparkles: 

# つくったもの

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55219/3c45d8c2-f39b-b3b1-a7fc-82a8ecd3e185.png">


https://text-lottery.vercel.app/

https://github.com/tamanugi/text-lottery

# 使用した技術

- Sveltekit
- tailwindcss
- Vercel

# くじびきのアニメーションについて

Svelteではtransitionアニメーションを簡単にコンポーネントに適用することができます。

例えばリストで `transtion:slide` を指定するだけで、リストの追加/削除時にいい感じにぬるっと動いてくれるようになります

```html
  {#each items as item}
    <div transition:slide class="flex justify-center items-center ">
    ...
    </div>
  {/each}
```

Transitionは用意されているものだけでなく、以下のようにオリジナルのものを設定することもできます

参考: https://svelte.dev/docs#transition_fn

```typescript
  function lotteryAnimation(node, option) {
    let items = $lotteryItemStore.filter((item) => item.enabled && item.text);

    items = shuffle(items);

    return {
      duration: 2000,
      easing: cubicOut,
      tick: (t) => {
        const i = ~~(t * 100) % items.length;
        node.textContent = items[i].text;
      }
    };
  }

　　　// usage
 // <div transition:lotteryAnimation>
```
　
`transtion:hoge` に指定する関数は以下のように `node` `option`　　の二つを引数にとります

```typescript
transition = (node: HTMLElement, params: any) => {
	delay?: number,
	duration?: number,
	easing?: (t: number) => number,
	css?: (t: number, u: number) => string,
	tick?: (t: number, u: number) => void
}
```

`tick`関数は  0 - 1 の値 `t` を引数にとります
この`t`は`easing`に指定された関数によって生成されます 

これによって最初は細かく切り替わり、終盤はゆっくり切り替わるような動作を再現することができました🎉

![ezgif-2-79851cbc79c9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55219/6d3bd607-cf9a-7dfb-eacd-3c39ecac7eda.gif)

# まとめ

もし何かくじ引きなどすることがあれば使っていただけると幸いです。
何かありましたらPRなども投げてもらえると嬉しいです :sparkles:
リーダブルコードを読んでの個人メモ(1)

##メモ
**1.明確な単語を選ぶ**
**2.凡用的な名前を避ける（使う状況を選ぶ）**
**3.具体的な名前を使う**
**4.接尾辞や接頭辞を使って情報を追加する**
**5.名前の長さを決める**
**6.名前のフォーマットで情報を伝える**


**send**の代替案

|単語|単語の意味|
|:--|:---:|
|delivery|配送|
|dispatch|急送、発送|
|announce|発表する、知らせる|
|distribute|分配する、配る|
|route|決まったルートを経て送る[届ける]|

**find**の代替案

|単語|単語の意味|
|:--|:---:|
|search|探す、捜索|
|extract|取り除く|
|locate|（場所を）探し当てる|
|recover|回復する、取り戻す|

**start**の代替案

|単語|単語の意味|
|:--|:---:|
|launch|開始する|
|create|作成|
|begin|始める|
|open|開ける|

**make**の代替案

|単語|単語の意味|
|:--|:---:|
|create|作成|
|set up|設定、並べる|
|generate|生成する|
|compose|構成する|
|add|加える|
|new|新しい、新品|



**filter()**
例)DBに問い合わせる場合を想定するとfilterは曖昧
・select (選択)
・exclude (除外)

**限界値を決めるときはmaxとminを使用する**
・max_　（最大）
・min_　（最小）

**範囲を指定するときはfirstとlastを使用する**
・first（始まり）
・last （終わり）

**包含/排他的範囲にはbeginとendを使用する**
・begin（始める）
・end　（終わる）

**ブルー値(true,false)に名前をつけるとき**
・is + 形容詞
　ex) isEnabled = 現在有効

・has + 過去分詞
　ex) hasSent = 送信済み
Dockerfileでヒアドキュメントが使えるようになった

## アナウンス記事

https://www.docker.com/blog/introduction-to-heredocs-in-dockerfiles/

## リファレンス

https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md#user-content-here-documents

## 例

### 従来のDockerfile

公式のベストプラクティスに従って、複数のapt-getを&&で繋いで一つのRUNに収めています。

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run

```Dockerfile:Dockerfile.slim
FROM node:slim
RUN apt-get update && apt-get install -y \
    tini \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/usr/bin/tini", "--"]
USER node
WORKDIR /home/node
COPY --chown=node:node package.json package-lock.json ./
RUN npm install --production && npm cache clean --force
COPY --chown=node:node index.ts ./
CMD ["node_modules/.bin/ts-node", "index.ts"]
```

### これからのDockerfile

複数のapt-getを書く箇所がヒアドキュメントを使ってより見やすく書くことができるようになりました。
現時点では、先頭に`# syntax=docker/dockerfile:1.3-labs`が必要な点と、エディタのシンタックスハイライトが対応していない場合があるという点で注意が必要です。

```Dockerfile:Dockerfile.slim
# syntax=docker/dockerfile:1.3-labs
FROM node:slim
RUN <<eot
apt-get update
apt-get install -y \
  tini
apt-get clean
rm -rf /var/lib/apt/lists/*
eot
ENTRYPOINT ["/usr/bin/tini", "--"]
USER node
WORKDIR /home/node
COPY --chown=node:node package.json package-lock.json ./
RUN npm install --production && npm cache clean --force
COPY --chown=node:node index.ts ./
CMD ["node_modules/.bin/ts-node", "index.ts"]
```

## わかりやすい差分

https://github.com/umireon/umireon-docker-node-dockerfile-templates/pull/1/files#diff-d8dcf21624927ddf769f7045c3f598ef432a45cd04a884591783a39a04cd6402
[シリーズ 全6回] subprocessの代替パッケージ「sh」(amoffat/sh)を使ってみる

# はじめに

標準パッケージでは無いものの subprocess の代替である「sh」(amoffat/sh) も便利である.

個人的な考えではあるが、「sh」は標準パッケージでは無いので、職場などで使い込むと
他者の迷惑になり兼ねない。しかし、適度に使う分には subprocess よりも速く実装できて
好都合なので書き残しておく.

|コンテンツ|実装時期|
|:--|:--|
|[[06] subprocessの代替パッケージ「sh」を使ってみる ... Git 操作をする](https://qiita.com/robozushi10/items/56964235a84c649bc0e5)|2019/10|
|[[05] subprocessの代替パッケージ「sh」を使ってみる ... sudo をパスワード自動入力で使う](https://qiita.com/robozushi10/items/650f8521ffabdfb5f01e)|2019/10|
|[[04] subprocessの代替パッケージ「sh」を使ってみる ... sudo を使う](https://qiita.com/robozushi10/items/4b613de3fd84776ff776)|2019/10|
|[[03] subprocessの代替パッケージ「sh」を使ってみる ... findコマンド](https://qiita.com/robozushi10/items/dd9f1e72860ae727f77f)|2019/10|
|[[02] subprocessの代替パッケージ「sh」を使ってみる](https://qiita.com/robozushi10/items/7fee38be93b4c0fc014c)|2019/10|
|[[01] subprocessの代替パッケージ「sh」を使ってみる](https://qiita.com/robozushi10/items/815748c274a3a54af4b2)|2019/10|