OmniAICreator/Qiita-1.07M huggingface dataset:
Omit<T,K> はやりすぎると any になる

## 問題点

型を色々と合併したり交差した後、`Omit` でプロパティの消去を行うと空になってしまうことがあります。そして、`Omit<>` を使用して全てのプロパティが消失すると `any` として振舞ってしまいます。

例えば、`REST API` があって、 `API` 型を定義して、こんな感じで使ったりします。

```ts
/** リクエストの共通パラメータ */
type REQEST_COMMON = {
  random: number;
};

/** レスポンスの共通パラメータ */
type RESPONSE_COMMON = {
  random: number;
  result: number;
};

/** SET_VALUE と GET_VALUE という API のリクエストとレスポンスのパラメータ */
type API = {
  SET_VALUE: {
    REQUEST: REQEST_COMMON & { selector: "SET_VALUE"; value: number; };
    RESPONSE: RESPONSE_COMMON & { selector: "SET_VALUE"; };
  };
  GET_VALUE: {
    REQUEST: REQEST_COMMON & { selector: "GET_VALUE"; };
    RESPONSE: RESPONSE_COMMON & { selector: "GET_VALUE"; value: number };
  };
};

/**
 * 以下のポリシーで selector と random を Omit する
 * - selector は引数として与えられるので不要
 * - random は共通パラメータなので callApi に処理を集約するため不要
 **/
function callApi<T extends keyof API>(
  selector: T,
  parameter: Omit<API[T]["REQUEST"], "selector" | "random">
): Promise<API[T]["RESPONSE"]> {
  return new Promise<API[T]["RESPONSE"]>((resolve, reject) => {
    /** 何らかの非同期処理（http postする的な） */ 
  });
}

/** 呼び出し側のコード */
callApi("SET_VALUE", {value: 123})
.then(re => {});

callApi("GET_VALUE", {})
.then(re => {})
```

ここまでは良いのですが、問題は下記のコードが許されてしまうことです。

```ts
callApi("GET_VALUE", {value: 123})
.then(re => {})
```

`GET_VALUE` では `value` というプロパティを指定することはできない筈ですが、何故かエラーが発生せず、間違いに気付きにくいです。
寛容な `REST API` であれば、無駄なプロパティを設定しても受け入れてくれるかもですが、厳格 `REST API` だとパラメータチェックでエラーになるかも知れません。

これが何とかならないのかというのが、今回の問題です。

## 考察

### 問題を整理

「ことの発端」ではグチャグチャとコードを書いていますが、問題を単純化すると次のようなケースになります。

```ts
type X = {
    x: number;
};

/** プロパティを設定することはできない筈だがエラーにならない */
const x: Omit<X, "x"> = {
  x: 123,
  hoge: "fuga"
};
```

### ネットを漁る

`Omit<T,K>` の `K` が `keyof T` じゃないのは何でだ！的な熱い議論がされているようですが、`Omit` によって空っぽ（`{}`型）になった場合について私は記事を見つけることができませんでした。

https://github.com/microsoft/TypeScript/issues/30825

Typescript って静的解析なんだから `keyof T` にすべきじゃないかと思いますけど、ここは互換性を考慮しているのかな？
まぁ、そうしたいなら、自分で作れば良いって感じですかね。


### `{}`型って `any` なの？

`{}` 型　は `any` のように振舞まうことが確認されます。

```ts
const x: {} = {
   a: 1
};
```

で、この `{}`型は TypeScript の型としてどういう取り扱いなのかを確認してみました。

```ts
type _1 = {} extends any ? 1 : 0; /** _1 は 1 */
type _2 = any extends {} ? 1 : 0; /** _2 は 0 | 1  */
```

これで分かることは。。。

* `{}` 型は `any` からの派生である
* `any` は `{}` 型からの派生でもあるし、そうとも言い切れない

`_2` の結果についてはシュレーディンガー的な感じで想定外でしたが、`extends {}` は使えそうな予感がします。

## 解決案

と、まぁ、浅い考察の結果 `Drop` というジェネリクス型を作ってみました。

```ts
/**
 * EmptyType.ts のように別ファイルにして
 * EmptyType のみ export することで EMPTY_SYMBOL を隠蔽することが望ましい
 **/
const EMPTY_SYMBOL = Symbol();
type EmptyType = {[EMPTY_SYMBOL]?: never};

type Drop<T, K extends string | number | symbol> =
  {} extends Omit<T, K> ? EmptyType : Omit<T, K>;

type X = {
  x: number;
};
type Y = {
  y: number;
};

const _1: Drop<X, "x"> = {
  x: 1 /** <-- エラー */
}

const _2: Drop<X & Y, "x"> = {
  y: 1
}

const _3: Drop<X & Y, "x"> = {
  y: 1,
  x: 1 /** <- エラー */
}

const _4: Drop<X & Y, "x" | "y"> = {
  y: 1 /** <- エラー */
}

const _5: Drop<X & {}, "x"> = {
  x: 1 /** <- エラー */
}
```

当初`{}`型の表現は`{"\0"?: undefined}`だったり、`{[Symbol.iterator]?: undefined}`だったりしましたが、最終的に非公開の`symbol`を生成してから`EmptyType`を定義することで落ち着きました。
nl2brとは？何の略？

# よく見かけるnl2brとは？

改行文字を\<br>の前に挿入するPHPの組み込み関数みたいです

改行文字 = \r\n、 \n\r、\n、\r
これらの文字列の前に<br>をいれてくれる

# 何の略？
Newline to br
の略だそうです

***
仕事の中で最近よく見かけたのですが、あまり気にせずだったのでこの機会に調べてみました

ご参考になれば幸いです
adbコマンドでMeta Questが認識されない不具合の直し方

タイトルの通りですが、WindowsPCとMeta Quest(旧：Oculus Quest)をUSBケーブルで接続して、
「adb install」がうまくいかず、「adb devices」をしてもリストに表示されなくなっていました。

# 解決方法
こちらのページが見つかり、adbのバージョンが古い事が原因らしいとわかりました。ちょうど自分のadbもバージョンが1.0.32でした。
https://www.scriptlife.jp/contents/programming/2019/06/23/oculus-quest-adb/
Android StudioのSDK Managerを使用し、「Android SDK Command-line Tools(latest)」と、「Google USB Driver」をインストールし、
adbのバージョンを最新の1.0.41に更新した所、「adb devices」と「adb install」が正常に動くようになりました。

# 解決するまでに試した事
・Meta Questの再起動(効果なし)
・パソコンの再起動(効果なし)
・Meta Questの開発者モードの有効状態を切り替え(効果なし)
・USBケーブルの再接続(効果なし)
WindowsのエクスプローラーからはMeta Questが見えているので、ケーブルの問題ではなさそうでした。

# 苦労した事
解決方法はわかったのですが、何度SDK Managerでadbを更新しても問題が解決せず、色々と試していたのですが、
ふと今更新しているadbとは別のadbを使っているのでは？と思い、環境変数のPathを確認してみたところ、
2つの場所にadbがある事がわかりました。
更新していなかったもう一つのadbを同様の手順で最新にしたところ、「adb devices」と「adb install」が正常に動くようになりました。
Microsoft Learn のコレクションに Microsoft Docs のページも追加できる！ #MSLearn

最近、Microsoft Learn のコレクションに Microsoft Docs のページも追加できることを知りまして、自分と同様に気付いていない方のために記事としました。

## Microsoft Learn とは
Microsoft Learn は、Microsoft 製品についての対話式学習などを提供する無料のオンライン トレーニング プラットフォームです。
※[Microsoft Learn FAQ](https://docs.microsoft.com/ja-jp/learn/support/faq?pivots=general#what-is-microsoft-learn)より引用

Microsoftアカウントが無くとも学習コンテンツにアクセスすることは可能ですが、Microsoftアカウントでサインインすると、以下の機能が利用できます。
* 学習アクティビティの進行状況の追跡
* モジュールのコレクションの作成と共有
* ブックマークの保存
* ポイントとアチーブメントの獲得
* 無料の Azure リソースの利用
* パーソナライズされた推奨事項の表示

## Microsoft Learn の構成
以下の構成となります。
* ラーニングパス・・・モジュールの集合
  * モジュール・・・ユニットの集合
    * ユニット・・・学習コンテンツ、対話式アクティビティ、知識チェックなど

#### ラーニングパス
* 特定の役割 (開発者、アーキテクト、システム管理者など) またはテクノロジ (Azure Web Apps、Power BI、Xamarin.Forms など) を中心に構成されたモジュールの集合です。
* ラーニング パスを完了すると、学習したテクノロジや役割のさまざまな側面について新しい理解が得られます。さらにトロフィーも授与されます。

#### モジュール
* Microsoft Learn エクスペリエンスの構成要素で、 1 つのモジュールは、動画、ラボ、記事などの関連ユニットの集合を含む 1 つのコースだと考えることができます。
* モジュールを完了すると、テクノロジに関連する新しいスキルが得られます。さらにバッジも授与されます。

#### ユニット
* モジュールに含まれる情報の小さな単位です。 学習コンテンツ、対話式アクティビティ、クイズなどがあります。
* ユニットを完了すれば新しい事柄を学び、XP (経験値) を獲得することができます。

## Microsoft Learn のコレクション機能 とは
コンテンツのセットを簡単に編集して整理し、コレクションのURL を展開することで他のユーザーと共有することができます。

Microsoft Learn ではMicrosoftが体系的にまとめてパッケージした[ラーニングパス](#ラーニングパス)や学習コースの最小単位である[モジュール](#モジュール)が用意されていますが、これらとは別にユーザー独自のラーニングパスを作成でき、共有もできます。

コレクションの作成などコレクション機能の使い方は以下のページで分かりやすく解説しています。
* Learn コレクションを発表
  https://docs.microsoft.com/ja-jp/teamblog/announcing-learn-collections

## Microsoft Learn のコレクションに Microsoft Docs のページも追加できる！
これまでコレクションを作成するときは、Microsoft Learn のラーニングパスやモジュールをコレクションに追加して、独自のラーニングパスを作成していました。

しかし、新たなオリジナルラーニングパスのためのコレクションを作成したときに、Microsoft Docs のページのタイトルの右側に＋ボタンがあることに気付き、Microsoft Learn のコレクションに追加できることが分かりました。

#### Microsoft Docs のページをコレクションに追加
![Docsをコレクションに追加.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38910/7ed4fc09-07af-4134-4276-547aeb87dfb6.gif)


#### コレクションに追加した Microsoft Docs のページを開く
![コレクションからDocsを開く.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38910/fb3debf5-908d-1b46-22b6-200939ac85e8.gif)



## まとめ
Microsoft Learn のコレクションなので、Microsoft Learn 内のコンテンツのみ追加できると思い込んでいましたが、実際には Microsoft Docs 内のコンテンツであればドキュメントだけでなく動画ページやイベントページなどもコレクションに追加できます！

コレクション機能は独自のラーニングパスだけではなく、技術記事やリファレンスのスクラップとしたり、学習用のサンプルコードのブックマークとしたり、アイデア次第で活用の幅が広がるスゴイ機能でした。
SoftEther VPN Client 自動起動 自動接続 無効 にするには

SoftEther VPN Client が気付くと繋ぎっぱなしになってる
手動で切断辛くて困ってた

いくつか無効を試みたが、どの方法もだめだった

しかし、コマンドラインで切断する方法はあった

切断コマンド
vpncmd /CLIENT localhost /CMD AccountDisconnect 接続設定名

接続設定名がわからん

接続設定名を確認しよう

接続設定一覧の取得のコマンド
vpncmd /CLIENT localhost /CMD AccountList
<pre><code>AccountList コマンド - 接続設定一覧の取得
項目               |値
-------------------+-----------------------------------------------
接続設定名         |vpnABC
状態               |接続完了
接続先 VPN サーバー|**************************** (直接 TCP/IP 接続)
仮想 HUB 名        |*******
仮想 LAN カード名  |***
-------------------+-----------------------------------------------
接続設定名         |vpnDEF
状態               |オフライン
接続先 VPN サーバー|**************************** (直接 TCP/IP 接続)
仮想 HUB 名        |*******
仮想 LAN カード名  |***
コマンドは正常に終了しました。</code></pre>

切断してみる
vpncmd /CLIENT localhost /CMD AccountDisconnect vpnABC

でも毎回手動でコマンドうつのだるい

再起動で切断するようにしてみるか

テキストファイルに
vpncmd /CLIENT localhost /CMD AccountDisconnect vpnABC
って書いて、名前を付けて保存
disconnect_vpn.bat
で名前いいか

あとは起動で実行するスタートアップの場所
エクスプローラに
shell:startup
と入力

ここに
disconnect_vpn.bat
置いとけば間違いないはず。

再起動してみよう。

いけた。

再起動で切断できないなら
再起動で自動切断すればいいじゃない。
2定点と直線上の動点との距離の和「22年 長崎大 文系2 理系4」をsympy でやってみた。

オリジナル

https://kamelink.com/blog/2022/06/18/6-6-22-nagasakidai-bunnkei2-rikei4/

①ベクトルでやっていません。
②誘導(3)の使い方がわかりませんでした。
アドバイスをお願いします。

# sympyで

```python
from sympy import *
var('t u v')
OO=Point(0,0,0)
OA=Point(1,2,3)
OB=Point(1,1,-1)
OC=Point(7,3,5)
#
OP=t*OA
BP2CP2=OP.distance(OB)**2+OP.distance(OC)**2
print("#(1)",BP2CP2.expand())
ans=solve(diff(BP2CP2),t)[0]
OP=ans*OA
print("#(2) 目的",OP,BP2CP2.subs({t:ans}))
#
OH=Line(OO,OA).projection(OB)
OK=Line(OO,OA).projection(OC)
print("#(3)",(OH-OB).dot(OK-OC)/(OH.distance(OB)*OK.distance(OC)))
OP=u*OA
BPCP2=(OB.distance(OP)+OC.distance(OP))**2
ans=solve(diff(BPCP2),u)[0]
OP=ans*OA
print("#(4) 目的",OP,sqrt(BPCP2.subs({u:ans})))
print("#(4) ",solve((OK-OH)-v*(OP-OH),v)[v])
#(1) 28*t**2 - 56*t + 86
#(2) 目的 Point3D(1, 2, 3) 58
#(3) 5/9
#(4) 目的 Point3D(1/2, 1, 3/2) 2*sqrt(26)
#(4)  4
```
NSURLErrorDomain Code=-1017 "cannot parse response"について

# 原因不明のエラー
現在、自分が管理しているiOSアプリで`cannnot parse json`というエラーが出ました。
firebaseの使用が主な原因かと。。
stack overflowやその他のエンジニアのウェブサイトで調べても解決策がでこなくて焦っていました。
調べてみると、Safariなどでもこのようなエラーが起きていたようで、ネットワークレベルが弱いことが原因の一つであるとわかりました。
まだ再現できただけで、問題の解決はしていませんが共有いたします。

# 再現方法
Xcode Simulatorを使用して再現します。
まず[ここ](https://developer.apple.com/download/all/?q=Network)から**Additional tools for Xcode**をダウンロードします。
dmgの中に**Hardware**フォルダがあるのでそこを開きます。その中の**Network Link Condirioner.prePane**を実行します。
すると設定の中に追加されます。macOS Venturaにしてしまったので設定画面が違うのはご了承ください...
![スクリーンショット 2022-07-01 19.00.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186268/6b719171-529d-347b-1cda-3a2246a49528.png)
`Manage Profiles...`で写真と同じようなネットワークレベルを新しく作成します。
‹![スクリーンショット 2022-07-01 19.06.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186268/c3e7b86f-ad4e-53aa-cbe4-29f330d49817.png)
オフラインではないが、かなり弱いネットワークにするのが重要です。
これで電波の弱いネットワークの準備ができましたので、Simulation内でネットワーク通信(httpsCallableなど)を実行すると100%ではありませんが再現が可能です。
なぜ100%出ないかは恐らく、通信が完了するまでにタイムアウトしてしまうのが原因かと思われます。

# 解決案
エラーハンドリングを各所できちんと実装するのが一番手っ取り早いかと思います。
ネットワーク速度を計測するという手も考えましたがさすがに手間がかかりそうですので、今回はエラーハンドリングで対処しようと思います。
管理者ユーザー機能の実装[Ruby, Rails]

初めまして、プログラミング初学者"fujitacoma"です！

4月からプログラミングスクールで学習を始めておりましたが、
遅ればせながらのQiita初投稿です。

今回は、現在開発中のオリジナルアプリにて簡単な管理者機能を実装しましたので、
その流れを説明していきたいと思います！

# はじめに

今回使用するGemはdeviseのみです。
deviseのインストール及び、usersテーブル作成後から説明したいと思います。

# 管理者(admin)を追加する

まずはじめに、作成したusersテーブルに管理者(admin)を追加します。

```

#ターミナル
 rails g migration AddAdminToUsers

```
この記述の命名規則は、キャメルケース、、でしたかね。
大文字と小文字ががラクダのコブのように続く＝キャメルケース
って感じで覚えた気がします。

続いて、作成されたマイグレーションファイルにカラムの情報を追加していきます。
このとき、カラムの型はboolean型、デフォルトは0とします。

```ruby

#migrationファイル
class AddAdminToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :admin, :boolean, default: false
  end
end

```
記述ができたら、、
```

#ターミナル
 rails db:migrate

```
忘れず実行しましょう！
ちなみに私はコロンをよく忘れて面倒なことになります。

# 管理者ユーザーの情報を追加する

次に、管理者ユーザーの情報を登録していきます！
カリキュラムでは一度も使用しなかった、seeds.rbファイルに記述していきます。
```ruby

# seeds.rb

User.create!(username:  "管理者",
             email: "admin@example.jp",
             password:  "11111111",
             password_confirmation: "11111111",
             admin: true)


```
上記はあくまで例ですので、
ご自身で設定されたusersテーブルのカラム名に沿って編集ください。

記述ができたら、
```

#ターミナル
 rails db:seed

```
こちらも初めましてなコマンド。
seeds.rbファイルを使用したことがなかったので当然ですが。

最後にデータベースに登録した管理者ユーザーの情報が保存されているか確認しましょう。

以上で、管理者ユーザーの追加が完了しました！
あっという間ですね。

これで晴れて、
current_user.admin?
等のメソッドが使用できるようになり、条件分岐による管理者機能が実装できます！

# 管理者機能に有用なGem

①ActiveAdmin
管理者画面を生成してくれるGemです。
deviseによる管理者機能と連携させて使うのが良いそうです。
GitHub URL : https://github.com/activeadmin/activeadmin

②rails_admin
こちらも管理者画面を生成してくれるGemです。
ActiveAdmin同様、deviseによる管理者機能と連携させて使うのが基本だそうです。
GitHub URL : https://github.com/railsadminteam/rails_admin

③cancancan
管理者権限を設定できるGemです。
同じくdeviseによる管理者機能と連携させて使うのが基本となり、
ActiveAdminやrails_adminとの併用も便利なようです。
GitHub URL : https://github.com/CanCanCommunity/cancancan

いろいろありますね！
また、機会があれば実装してみたいと思います！

かなり古い記事ですが、管理者機能の実装方法選択の参考になります。
https://qiita.com/baban/items/f751fb05c4d2367878aa

# 最後に

ここまでお読み頂き、有難うございました！
初学者なりに調べつつ記載しておりますが、
ご指摘やアドバイスがあればコメント頂けますと幸いです！
Vueでボタンを別コンポーネントにする

Vueにはコンポーネントという仕組みがあり、ボタンやフォームなどのWebサイトで使うパーツを別ファイルで部品化して使い回せるように作ることもできます。
そこで、ボタンを部品化してみました。

部品化したボタンコンポーネントはこちらです。

```php:ButtonComponent.vue
//ボタンを別コンポーネントにする
<template>
  <div class="BtnCpnt">
    <buttoncpnt>送信</buttoncpnt>
  </div>
</template>
<script>

</script>
<style>
.app{
    background-color: #afeeee;
    border-radius: 1.5em;
    box-shadow:0 0.2em 0.5em rgba(0,0,0,0.2);
    padding:1em 2em;
    color: #2f4f4f;
    font-weight: bold;
    text-decoration: none;
}
</style>
```

コンポーネントを配置する側のソースは以下。
```
<template>
  <div class="app">
    <BtnCpnt 
      @click="dialogOutput"
    />
  </div>
</template>
<script>
import BtnCpnt from "../components/ButtonComponent.vue";
export default{
    components: {
        BtnCpnt
    },
    data () {
      return {

      }
    },
    methods: {
      dialogOutput() {
        alert('送信しました')
      }
    }
};
</script>
```
ボタンを押下するとダイアログが出るようなものにしてみました。
実行結果はこれ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725725/d01dd536-c390-76b5-75ac-b0e59a3676af.png)

個人的にマジックナンバーがすごく気になってしまうので
CSSで設定している値など定数化して改良してみたいです。
レスポンシブデザイン

広島市でメンズ専門の脱毛サロンを経営しています。

html にて自店のHPをグループ内で作成しています。

最近レスポンシブデザインに変更しましたが、画像サイズをスマホで見たときとPCで見たときに切り替える方法が、もっと良い書き方があるのではと思っています。

当店のHPです。
https://datsumou-menz.com/
javascript - Array.prototype.find()

仕事で身に付けた技術や仕事以外で身に付けた知識を、自分用の備忘録として投稿していきたいと思います。

# 今日の内容
会社で先輩方にしていただいた、Vue.jsで書いたコードのフィードバックで、javascriptの関数であるArray.prototype.find()を初めて使ったので、備忘録として残します。

## 初めて使った関数
- Array.prototype.find()
配列から指定した条件をクリアした最初の要素を返す。クリアした要素がなければ undefined を返す。

## 使うきっかけになったコード(サンプル)
配列型の２つの変数newArrayとoldArrayがある。
newArrayの要素がoldArrayの中になければその要素を返すというコードを書いた。返ってくる要素は多くて1つであると分かっている。
~~~ vue:before.vue
this.oldArray.filter(
  (value)=>this.newArray.indexOf(value) === -1
);
~~~

## before.vueの良くないところ
before.vueでは、oldArrayの要素全てを調べて、条件をクリアする要素からなる新しい配列を作成する。返ってくる要素は多くて1つと分かっているので、条件をクリアした最初の要素を見つけるとその要素をreturnするfind()を使って書く方が、無駄な処理がなくなる。

## コードの改善
~~~ vue:after.vue
this.oldArray.find(
  (value)=>this.newArray.indexOf(value) === -1
);
~~~

## おまけ
返り値は異なるが同じ処理をしている関数がある。
- Array.prototype.find()
配列から指定した条件をクリアした最初の要素の位置を返す。クリアした要素がなければ -1 を返す
Google billboard puzzle

# Google billboard puzzle

![スクリーンショット 2022-07-01 18.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/bea43e2d-24f6-491f-98d5-be6df00c41ca.png)

```julia
using Primes
setprecision(BigFloat, 1000)
s = string(big(ℯ))
for i in 3:length(s)-9
    s[i:i] == 0 && continue
    isprime(parse(Int, s[i:i+9])) && (println(s[i:i+9]); s[i:i+9]; break)
end
```

    7427466391


the answer to this equation ...

    f(1)= 7182818284
    f(2)= 8182845904
    f(3)= 8747135266
    f(4)= 7427466391
    f(5)= __________ 



```julia
using Primes
setprecision(BigFloat, 1000)
s = string(big(ℯ))
count = 0
for i in 3:length(s)-9
    (s[i:i] == 0 || sum(parse.(Int, split(s[i:i+9], ""))) != 49) && continue
    (count += 1; count == 5) && (println(s[i:i+9]); break)
end
```

    5966290435
PythonでArcGISを操作する環境構築をしてみた

# はじめに
PythonでArcGISを操作できるように環境構築してみた

# 前提
1.Anacondaがインストールしてあること

2.Anacondaのバージョンが最新であること
　最新にしていない方は下記コマンド実行
```
conda update -n base -c defaults conda
```

3.pipがインストールしてあること

4.Anacondaがactivateであること
```
conda activate

(base)xxxxx
```

# 手順
1.下記コマンドを実行する
```
conda install -c esri arcgis
```

下記コマンドを実行し、ArcGISがインストールされていることを確認
```
conda list

>　arcgis                    2.0.1                 py39_2826    esri
```

※エラーが発生し、ArcGISがインストールできない場合は下記を実行
```
conda install -c esri arcgis --no-deps
```

2.下記を実行し、pipenvをインストールする
```
pip3 install pipenv
```

3.下記を実行し、pipenvにArcGISのAPIをインストールする
```
pipenv install arcgis
```

# 公式ガイド

https://developers.arcgis.com/python/guide/install-and-set-up/
ArcGISを使って地図を表示させる

# はじめに
ArcGISを使って地図を表示する方法をまとめた

# 環境
エディタ：おまかせ（CodePenが楽）

https://codepen.io/pen/?editors=1000

言語：HTML、CSS、JavaScript

# 手順
※手順2以降は追加行を☆で表す

1.Webブラウザウィンドウの全幅と高さのマップを作成します。
```html
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title>ArcGIS API for JavaScript Tutorials: Display a map</title>

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>

  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>
```

2.headタグにCSSファイルとJSライブラリへの参照を追加します。
```html
    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>

☆   <link rel="stylesheet" href="https://js.arcgis.com/4.24/esri/themes/light/main.css">
☆   <script src="https://js.arcgis.com/4.24/"></script>
```

3.ArcGISのモジュールを追加
```html
    <link rel="stylesheet" href="https://js.arcgis.com/4.24/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.24/"></script>

☆   <script>
☆     require(["esri/config","esri/Map", "esri/views/MapView"], function (esriConfig,Map, MapView) {
☆
☆     });
☆   </script>
```

4.開発者ダッシュボード画面からAPIキーを取得します

https://developers.arcgis.com/dashboard/

5.APIキーを記載します
```html
    <script>
      require(["esri/config","esri/Map", "esri/views/MapView"], function (esriConfig,Map, MapView) {

☆       esriConfig.apiKey = "ここにAPIキーを記載する";
☆
☆       const map = new Map({
☆         basemap: "arcgis-topographic" // Basemap layer service
☆       });
```

6.地図を表示させます
```html
        const map = new Map({
          basemap: "arcgis-topographic" // Basemap layer service
        });

☆       const view = new MapView({
☆         map: map,
☆         center: [-118.805, 34.027], // Longitude, latitude
☆         zoom: 13, // Zoom level
☆         container: "viewDiv" // Div element
☆       });
```

以上です
cscの作法 その221

# 概要
cscの作法、調べてみた。
秘密鍵pemファイルを、秘密鍵xmlファイルに変換してみた。

# サンプルコード

pem2xml

```
using System;
using System.IO;
using System.Security.Cryptography;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Security;
using System.Collections.Generic;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;

	class test0 {
		static void Main() {
			AsymmetricCipherKeyPair privateKey;
			using (var reader = new StreamReader(@"privatekey.pem", Encoding.ASCII))
			{
				var pemReader = new PemReader(reader);
				privateKey = (AsymmetricCipherKeyPair) pemReader.ReadObject();
			}
			var rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters) privateKey.Private);
			RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
			csp.ImportParameters(rsaParams);
			File.WriteAllText("privatekey0.xml", csp.ToXmlString(true));
			Console.WriteLine("ok");
		}
	}




```


以上。
ArcGIS for Pythonを使ってみた

# はじめに
GISとは「Geographic Information System」の略です
簡単に言うと、その土地の斜面の角度などのデータが見れるものです。

https://www.gsi.go.jp/GIS/whatisgis.html

ArcGISとは、その土地データを編集することのできるツールです。
ソフトは有料版と無料版があります。

https://www.esrij.com/products/arcgis/

余談ですが
筆者は卒論でメインでTNTmipsを使用したり、サブでArcGISを使用したりしていました。

https://www.opengis.co.jp/htm/catalog/catalog.html

今回はArcGISの提供しているArcGIS for Pythonについてまとめました。

# 一覧
A.地図を表示（JavaScript/HTML/CSS)

https://qiita.com/wooooo/items/7d418250edc0eb382914

B.環境構築（Python）

https://qiita.com/wooooo/items/7ee7d0128ba9d22007af

C.地図の作成〜保存〜検索

https://qiita.com/wooooo/items/95661b29b7d55935b1fb

https://qiita.com/wooooo/items/3e362882e445ebcba8b3
使いやすいログにするために気をつけること

## 概要
最近業務内でログを利用する機会が増え、このログ使いづらいなと思う点があったので記事として整理しました。

本記事では、問題・問い合わせがあった際の原因調査の用途でログを利用するものとして説明します。

※本記事で利用するログは、説明のために簡略化(タイムスタンプ、処理IDなどは省略)しています。


## 原因調査への利用が難しいログ

ログを問題・問い合わせの原因調査に利用する場合、当たり前ですが必要な情報が適切にログに出力されている必要があります。

ですが、以下のように情報が適切に出力されていない場合もあります。

### 必要な情報がログに記載されていない
例として、ECサイトにおいて商品区分単位で商品の売上を集計するバッチから出力されるログについて考えます。
```
INFO 商品区分売上集計 {"id":1}
INFO 商品区分売上集計 {"id":2}
INFO 商品区分売上集計 {"id":3}
```
このログ出力のまま実際にバッチがエラーを吐いて終了した場合、どのような事態になるでしょうか。

ログを確認しても商品の売上集計についてのログは残っておらず、エラーが発生した箇所がわからないのでおそらく原因調査は難航するでしょう。

このような事態を避けるには、「該当箇所で問題が発生した際に、自分がそのログを確認して十分な情報が得られるか」を基準にするといいと思います。

今回の場合は集計対象(商品区分・商品)ごとに以下の項目があれば十分でしょう。
- 処理概要
- 処理概要パラメータ(id)

上記の例の場合も、「エラー発生時にどの商品売上集計時にエラーが発生したのかわからないと困るな」と考えられれば役に立つログに改善できます。


### 必要ない情報までログに記載されている
前の例は必要な情報が不足しているという話でしたが、一方で必要ない情報までログに出力している場合もあります。

例えば、以下のようなログです。
```
INFO 商品売上集計 {"id":1, "name":"よくわかるログ出力", "price":2500, "category":"書籍" ...}
```
このログは商品の情報を全て出力する勢いですが、通常時のログを確認する際は`id`などによって処理対象を識別ができれば十分であることが多いです。(少なくとも自分の経験上はそうです)

何より必要のない情報までログに出力すると、本来確認したい項目を見つけることが難しくなり作業時間や意欲を失うことにも繋がります。

そのため、今回の場合は通常時のログは以下の項目し、
- 処理概要
- 処理概要パラメータ(`id`)

エラー発生時のログは以下の項目を表示するなど、ログの役割に応じて必要な項目のみを出力すると役立つログになるでしょう。
- エラー情報
    - エラーメッセージ(例:`priceが負の値になっています。: price=-100`)
    - その他エラークラス名などの情報

## まとめ

以上、こんなログは使いづらいと思う点と、こうすると使いやすいのではという点を整理しました。

色々書きましたが、ログを改善するためには「どのようなログであれば利用者が使いやすいだろう」と意識してあげることが一番だと思います。
システム開発に限らない当たり前のことですが、忘れないように意識したいですね。
【PHP】PHPのuseの使い方

useとはスコープ外の変数を関数内で使用できる。

```PHP
<?php
$people = [
    ['name' => '太郎',  'age' => 19],
    ['name' => '洋子',  'age' => 37],
    ['name' => '美玖',  'age' => 21],
    ['name' => '信也',  'age' => 15],
    ['name' => '裕次郎','age' => 45],
    ['name' => '魁',    'age' => 8],
    ['name' => '達郎',  'age' => 55],
    ['name' => '真治',  'age' => 29]
];

$low = '20歳未満だから子供';
$over = '大人';
$age = 20;

$value = array_map(function($num)use($low,$over,$age){
    return ($num['age'] < $age ? $num['name'].'は'.$low : $num['name'].'は'.$over);
}, $people);

var_dump($value);
```

# 結果
```java
array(8) {
  [0]=>
  string(35) "太郎は20歳未満だから子供"
  [1]=>
  string(15) "洋子は大人"
  [2]=>
  string(15) "美玖は大人"
  [3]=>
  string(35) "信也は20歳未満だから子供"
  [4]=>
  string(18) "裕次郎は大人"
  [5]=>
  string(32) "魁は20歳未満だから子供"
  [6]=>
  string(15) "達郎は大人"
  [7]=>
  string(15) "真治は大人"
}
```
重回帰分析における AIC, BIC など

# 重回帰分析における AIC, BIC など

以下のデータ例をモデル式 `y ~ x1 + x2` で重回帰分析する。


```julia
using DataFrames

df = DataFrame(
    x1 = [46, 49, 55, 55, 52, 51, 53, 50, 50, 57, 51, 37, 45, 45, 54, 47, 54, 55, 40, 54],
    x2 = [49, 36, 50, 60, 54, 63, 44, 53, 53, 53, 48, 41, 44, 45, 53, 46, 59, 60, 47, 42],
    y  = [49, 40, 53, 61, 59, 50, 50, 50, 51, 52, 47, 41, 42, 44, 51, 48, 56, 61, 45, 47]);
```


```julia
using GLM, StatsBase

results = lm(@formula(y ~ x1 + x2), df)
```




    StatsModels.TableRegressionModel{LinearModel{GLM.LmResp{Vector{Float64}}, GLM.DensePredChol{Float64, LinearAlgebra.CholeskyPivoted{Float64, Matrix{Float64}}}}, Matrix{Float64}}
    
    y ~ 1 + x1 + x2
    
    Coefficients:
    ────────────────────────────────────────────────────────────────────────
                    Coef.  Std. Error     t  Pr(>|t|)   Lower 95%  Upper 95%
    ────────────────────────────────────────────────────────────────────────
    (Intercept)  1.64221     6.8959    0.24    0.8146  -12.9069    16.1913
    x1           0.433718    0.154839  2.80    0.0123    0.107038   0.760399
    x2           0.530437    0.11467   4.63    0.0002    0.288505   0.772369
    ────────────────────────────────────────────────────────────────────────



## 残差分散

サンプルサイズを $n$，独立変数の個数を $p$ とする。
残差平方和を $S_e$ とすれば，残差分散 $d$ は（1）式で定義される。

$\hspace{2cm}\displaystyle d = \sum_{i=1}^n (y_i-\hat{y_i})^2/n = S_e/n　　　　(1)$


```julia
n = nobs(results) # size(df, 1)
p = length(coefnames(results)) - 1
Se = sum((response(results) .- predict(results)) .^ 2)
```




    159.30705544126175




```julia
d = Se / n
```




    7.9653527720630874



## 対数尤度

対数尤度 $loglik$ は（2）式で定義される。

$\hspace{2cm}loglik = -0.5(n\log 2\pi + n\log S_e -n\log n + n) = -0.5(n\log 2\pi + n\log d + n)　　　　(2)$


```julia
loglik = -0.5*(n*log(2*pi)+n*log(Se)-n*log(n)+n) # loglik: 定義式により計算する
```




    -49.129782990684234




```julia
-0.5*(n*log(2*pi)+n*log(d)+n) # loglik: 定義式により計算する
```




    -49.129782990684234




```julia
loglikelihood(results) # loglikelihood メソッドで計算できる
```




    -49.12978299068424



## AIC

AIC の定義は（3）式で定義される。

$\hspace{2cm}AIC = -2loglik+2(p+2) = n\log 2\pi + n\log d + n + 2(p+2)　　　　(3)$


```julia
-2*loglik+2*(p+2) # AIC: 定義式により計算する
```




    106.25956598136847




```julia
n*log(2*pi)+n*log(d)+n+2*(p+2) # AIC: 定義式により計算する
```




    106.25956598136847




```julia
aic(results) # aic メソッドで計算できる
```




    106.25956598136848



なお，（3）式から定数部分を除いた（4）式による値を AIC とする場合もあるので注意が必要である。

$\hspace{2cm}AIC = n\log d + 2(p+1)　　　　(4)$


```julia
n*log(d)+2*(p+1) # AIC: 定義式により計算する
```




    47.50202465318156



## BIC

一般的に，「$-2\ \times$ 対数尤度$+ k\ \times$ パラメータ数」とすれば，AIC では $k=2$ である。

$k=\log($サンプルサイズ$)$ としたものは BIC または SBC(Schwarz's Bayesian criterion) と呼ばれる。


```julia
n*log(2*pi)+n*log(d)+n+2*(p+2) # AIC: 定義式により計算する
```




    106.25956598136847




```julia
n*log(2*pi)+n*log(d)+n+log(n)*(p+2) # BIC: 定義式により計算する
```




    110.24249507558443




```julia
bic(results) # bic メソッドで計算できる
```




    110.24249507558444
【python】Djangoで郵便番号の入力から住所を反映させる【Javascript】

# 郵便番号の入力から住所を自動で反映させる
フォームから住所を書く際に郵便番号を入力するだけで自動で住所が入力されたら楽なのでその流れをDjangoのコードで書けるようにメモ。
※既にアプリは出来てるものとして、その部分は割愛します。

## ルーティング設定(urls.py)
```python:urls.py
from django.urls import path,include
from .import views
from django.views.generic import TemplateView

app_name = 'アプリ名'
urlpatterns = [
    path('', views.IndexView.as_view(),name="index"),
    path('inquiry/', views.InquiryView.as_view(),name="inquiry"),
]
```
後にInquiry classを作る予定でこのpath設定。

## ビューの編集（views.py）

```python:views.py
from .forms import InquiryForm #forms.pyをインポート
from django.urls import reverse_lazy #処理が終わった後に画面に飛ばす処理

class InquiryView(generic.FormView):
    template_name = "inquiry.html"
    form_class = InquiryForm
    success_url = reverse_lazy('アプリ名:inquiry')
```

## フォームの設定(forms.py)

```python:forms.py
import os
from django import forms
from django.db.models import fields
#(省略)

Zipcode = {
    'zip_code':
        forms.TextInput(
            attrs={'class': 'p-postal-code','placeholder': '記入例：1060022'}, 
            ),
}

class InquiryForm(forms.Form):#クラス名は必要に応じて変える
# 郵便番号からcityまでを自動入力
    zipcode = forms.RegexField(label='郵便番号(ハイフンなし)',
        regex=r'^[0-9]+$',
        max_length=7,
        widget=forms.TextInput(attrs={'onKeyUp' : "AjaxZip3.zip2addr(this,'','state','city')"}),
    )
    state = forms.CharField(label='都道府県',max_length=6)
    city = forms.CharField(label='市区町村',max_length=10)
    address_1 = forms.CharField(label='番地',max_length=10)
    address_2 = forms.CharField(label='建物名・部屋番号',max_length=10)


    def __init__(self,*args,**kwargs):#入力フォーム表示用
        self.fields['zipcode'].widget.attrs['class']='form-control col-11'
        self.fields['zipcode'].widget.attrs['placeholder']='例：1600022 '

        self.fields['state'].widget.attrs['class']='form-control col-11'
        self.fields['state'].widget.attrs['placeholder']='都道府県をここに入力してください'

        self.fields['city'].widget.attrs['class']='form-control col-11'
        self.fields['city'].widget.attrs['placeholder']='市区町村をここに入力してください'

        self.fields['address_1'].widget.attrs['class']='form-control col-11'
        self.fields['address_1'].widget.attrs['placeholder']='番地をここに入力してください'

        self.fields['address_2'].widget.attrs['class']='form-control col-11'
        self.fields['address_2'].widget.attrs['placeholder']='建物名・部屋番号をここに入力してください'
```



## いい感じに動いてもらうためのJavaScript
今回はAjaxzip3を使ってるので、そこから引用してます。


https://github.com/ajaxzip3/ajaxzip3.github.io

※今回はbase.htmlにべた書きしましたが、他におすすめがあれば教えてください。

```javascript:base.html
    <script src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script>
```
SELECT文でのVALUE句

最近Treasure Dataでクエリを書いていて、INSERT文ではなくSELECT文でVALUE句を使用できると学んだので、備忘録として記載します。
```ruby
SELECT
　　*
FROM
　　(VALUES
　　　　(1, 'AAA')
 　　, (2, 'BBB')
 　　, (3, 'CCC')
 ) AS users（id, name)
```
実行結果は下記の通りです。
|id|name|
|--|----|
|1 |AAA|
|2 |BBB|
|3 |CCC|

ASのエイリアス部分は
```ruby
AS table_name(column1, column2...)
```
という風になっています。
なのでSELECT文を使用して、CREATEとINSERTを同時に行い、一時的にテーブルを作成するといったイメージでしょうか。

### 参考
https://www.postgresql.jp/document/9.6/html/queries-values.html
https://qiita.com/D-Three/items/62db5e03b9425f1ecb25
https://qiita.com/tiechel/items/f86f13f63feb3433e97c
Mac VScode Xdebug v3 でデバッグ

# この記事について
下記環境でのデバッグ設定でハマった部分を記載
・MacOS Bin Sur 11.3.1
・Vscode 1.68.1
・php 8.0.20 
・Xdebug 3.1.5
・XAMPP 8.0.19-0

# Xdebug 2 から 3にかけてphp.iniの記法が変わっている
ver2の時

    xdebug.remote_enable = 1
    xdebug.remote_autostart = 1
    xdebug.remote_port = 9000

ver3の時

    xdebug.mode = debug
    xdebug.start_with_request = yes

まあ、めちゃめちゃ公式に書いているんですが、、、（英語苦手）
https://xdebug.org/docs/upgrade_guide

# Mac M1チップ特有の対応

    file `which php`

で確認してからの

・arm64eの時

    arch -arm64 sudo pecl install xdebug

・x86_64の時

    arch -x86_64 sudo pecl install xdebug

公式はこちら
https://xdebug.org/docs/install


# Vscodeの設定

初歩的な気がしていますが、ハマりました、、、w

### テストスクリプトのデバッグ時の設定

↓のようなテストスクリプトでとりあえず動いてるか確認するとき

    <?php
    echo '1';
    ?>

"Launch currently open script"で、メニューバーのデバッグ開始(F5)を押す
![スクリーンショット 2022-07-01 16.14.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728526/057a0092-d1d3-667d-6b08-6758e22798c0.png)


### ブラウザ動作時のデバッグ
 ”Listen for Xdebug"にして、メニューバーのデバッグ開始(F5)しておいて、ブラウザ操作
![スクリーンショット 2022-07-01 16.09.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728526/4d9d1dfe-b025-6ab6-0f11-f50594e88980.png)


## 最後に
ネットサーフィンしまくりながらいっぱい探してたので
他にもあったと思いますが、覚えている部分のみ記載しています。
ありがとうございました。
AWS LightsailでWordPressを立ち上げる

# 概要
AWSでWordPressを立ち上げたい。
仮想サーバーはEC2でなく、Lightsailを使用する。
## なぜEC2でなくLightsail？
Lightsailは予めパッケージでOS,SMSが提供されているので、使いたいもの（今回だとWordPress）を選択するだけなので秒で作成できるため。

# WordPressを立ち上げる
## AWSコンソールにIAMユーザーとしてログインする
アカウントがない場合は先に作成しておく
https://aws.amazon.com/jp/

## 「仮想サーバーを使用して構築」を開始する
ログインしたらトップページの真ん中あたりにある「ソリューションを構築」から「**仮想サーバーを使用して構築**」を選択
![スクリーンショット 2022-07-01 15.30.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54443/06ad27f9-4faa-65c1-51d8-f7acc36532f0.png)

## Lightsailでインスタンスを作成する
プラットフォームは「**Linux/Unix**」
設計図は「**WordPress**」
![スクリーンショット 2022-07-01 15.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54443/1f9639db-3bdc-31b0-a101-967977f595e6.png)

あとはデフォルトのまま

## WordPressが作成される
最初は保留中でクリックできないが、一定時間が経つと実行中になるのでクリックして設定を進める
![スクリーンショット 2022-07-01 15.39.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54443/bf629866-e6c7-5c94-89d8-48b6b2af2ff7.png)

## アクセスできたら作成完了！
パブリックIPを使ってアクセス
`htts://54.***.**.***`

ログイン画面は
`htts://54.***.**.***/wp-admin/`

![スクリーンショット 2022-07-01 15.40.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54443/edd71bcd-ca6f-9cc5-4bcc-7aafe0ea2447.png)

秒でできた。。。

# FTPで接続する
## 鍵をダウンロードする
アカウントの**SSHキー**に入り、鍵をダウンロード
![スクリーンショット 2022-07-01 15.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54443/a85ebcec-e4c1-72a5-dfc2-9d0fd6ddfe45.png)

## ダウンロードした鍵を、任意のディレクトリに置く
`~/.ssh`の中に置いておけば基本的には良いと思います

## 接続に必要な情報
| 名称 | 情報 |
|:-:|:-:|
| 接続方法 | SFTP |
| サーバ（ホスト） | パブリックIP |
| ユーザ名 | bitnami |
| SSH Private Key | 前述でダウンロードした鍵を選択 |

接続できたら完了！
静電容量センサーの設計ポイントは何ですか？

静電容量センサーの高感度と高精度の独自の特性は、その正しい設計、正しい材料の選択、および微細な処理技術と切り離せません。センサーを設計する過程で、必要な範囲、温度、圧力の範囲内で、低コスト、高精度、高解像度、安定性と信頼性、良好な周波数応答などを実現するようにしてください。理想的なレベル。したがって、妥協案がよく使用されます。静電容量センサーの場合、その特性を開発し、その欠点を克服するために、次の側面を設計で考慮することができます。

周囲温度や湿度などの変化による誤差を減らし、断熱材の断熱性能を確保します。温度変化により、[センサー](https://pdf.chimicron.com/MLX91206LDC-CAH-001-RE-649143.pdf)内の各部品の幾何学的サイズと相互位置、およびある媒体の誘電率が変化し、それによって静電容量センサーの静電容量が変化し、温度誤差が発生します。湿度は、一部のメディアの誘電率と絶縁抵抗値にも影響します。したがって、温度などの誤差を低減し、材料の選択、構造、加工技術などの観点から、絶縁材料が高い絶縁性能を発揮するようにする必要があります。

![HTB1.Vdfl3vD8KJjSspl761IEFXa2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648141/98c42792-a31f-ea6c-128f-0e223834a73c.png)


静電容量センサーの金属電極の材質は、低温系の鉄ニッケル合金が好ましいが、加工が難しい。セラミックまたは石英に合金または銀をスパッタリングするプロセスも使用できるため、電極を非常に薄くすることができ、エッジ効果を低減するのに非常に有益です。

センサー内部の電極面は頻繁に清掃するのが不便ですので、ほこりや湿気を防ぐために密閉する必要があります。電極の表面に不活性金属（ロジウムなど）の非常に薄い層をめっきすると、シールに取って代わり、保護の役割を果たし、ほこり、温度、湿気、腐食を防ぎ、還元することができます。表面損失と温度係数の低下がありますが、コストは高くなります。

センサーでは、電極ホルダーは一定の機械的強度に加えて安定した性能を備えている必要があります。そのため、ブラケットには、温度係数が小さく、幾何学的なサイズ、安定性が高く、絶縁性が高く、吸湿性が低く、表面抵抗が高い材料が選択されています。たとえば、石英、雲母、宝石、およびさまざまなセラミックを使用できます。それらは処理がより困難ですが、それらの性能はプラスチックやプレキシガラスなどの材料よりもはるかに優れています。温度が高すぎない環境では、PTFEは優れた絶縁特性を備えています。これは選択時にも考慮することができます。

静電容量センサーの誘電体として、空気または雲母、および誘電体定数の温度係数がゼロに近い（湿度の変化の影響を受けない）他の誘電体を使用してみてください。シリコーンオイルや灯油などの液体を誘電体として使用した場合湿度が変化すると、それに応じて誘電率が変化し、誤差が生じます。この誤差は後続の電子回路で補償できますが、完全に除去することは容易ではありません。

可能であれば、センサーに差動対称構造を使用して、温度などのエラーを一部のタイプの電子回路（ブリッジなど）で減らすことができるようにする必要があります。

静電容量センサーの電源周波数として50kHzから数MHzを選択すると、センサーの絶縁部分の絶縁要件を減らすことができます。

センサー内のすべての部品は、組み立てる前に洗浄および乾燥する必要があります。静電容量値の変化や内部の水浸による絶縁劣化を防ぐために、センサーを密閉する必要があります。センサーシェルの剛性は、設置中の変形を避けるために優れています。
Chrome の Developer Tool (F12) でダウンロードするファイルコンテンツの情報を見る方法

# 問題

Chrome の F12 を開いてサーバーからどのような状況でコンテンツをダウンロードしてきたかを知りたいのだが、ダウンロードしてしまうと F12 の Newtwork タブ内にダウンロードしたコンテンツが記録されない。 そこで苦労したので、どのようにすればこのコンテンツタブ内にダウンロードするファイル情報が表示できるかを調べた。

# 対処

同一のタブ内で完結する場合の手順は以下の通りである。

- Chrome の設定 > ダウンロードで「ダウンロード前に各ファイルの保存場所を確認する」を有効にする
- コンテンツタブを開き、ダウンロード対象を見ることができるフィルタ (例: All, Media など) を設定する
    - もし区分が分からない場合は All を推奨
- ファイルのダウンロードを行い、そのダウンロードを保存するタイミングでキャンセルする
- すると、ダウンロード時のコンテンツ情報がコンテンツタブ内に記録されるので情報を確認する


なお、ダウンロードが別タブを開いた後に発生する場合は、Developer Tool の設定の Auto-open DevTools for Popup を有効にすれば大丈夫と思う（未確認）。
IK Rigを使って接地IKを実装してみました

UE5にてアニメーション回りの機能が充実して、IK Rigもその内の1つです。
オフィシャルドキュメントが用意されたとはいえ、EpicからはIK Rigをアニメーションのリターゲット用途についてチュートリアルを出しましたが、IK Rigを使ってキャラクターのIKの実装については触れてなかったのでIKリグを使ってキャラクターの足接地用IKを実装してみました。

# 実装環境
UE 5.02を使用して実装を行いました。
ThirdPersonテンプレートで提供されたBP_ThirdPersonCharacterを対象にIKを実装しました。

# デフォルトのIKの無効化
UE5のThirdPersonテンプレートではデフォルトでキャラクターの足接地IKが実装されておりますので、IK Rigの実装を行う前にはこのデフォルトのIKを外す必要があります。

デフォルトのIKはプロジェクトフォルダーの「ABP_Manny」のアニメーションBPのアニムグラフで実装されております。
![default ik.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/35e51265-d7e9-b9c2-a096-3b89449d65c3.jpeg)
こちらの画像の黄色枠で囲まれた部分がIKを行う処理です。
IKの処理を外すとこうなります：
![no ik.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/e2992fbf-a5c2-0fe5-a78a-0e08338b97de.jpeg)

これで実装の準備を整いました。

#　IK Rigの実装
[公式ドキュメント](https://docs.unrealengine.com/5.0/ja/ik-rig-solvers-in-unreal-engine/)を参考して、接地IK用のIK Rigを作成しました。
![ik rig setup.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/1a01a510-e671-8619-e1b9-8b1b1568be56.jpeg)
尻の位置補正を行うための「トランスフォームを設定」ソルバーと足の位置を補正する「手足IK」ソルバー2個で構成されます。
まだソルバーの挙動をアニメーションBP側で制御できるようにソルバーのIK目標のExpose Positionのチェックを入れます。
![expose position.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/175cd7b0-7345-fc90-9274-b4d12432fc42.jpeg)
次はアニメーションBPの方にIK Rig用の処理を実装していきます。
実装は[Historiaさんのチュートリアル](https://historia.co.jp/archives/3434/)を参考にして足の補正位置を計算します。
UE4のマネキンと違って、UE5のマネキンのスケルトンの中には最初から足IK用の補助ボーンが入っていますのでそちらを使用してライントレースの位置を決めていきます。
![event graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/840a786e-28b1-6aa1-5254-24d21685d627.jpeg)
Foot Trace関数の中身：
![foot trace.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/08d9f085-46d6-e2b3-adc6-1c0a2d1afced.jpeg)
AnimGraph：
![anim graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/8d1c3ca5-c76b-480f-1156-7df1a40ed04d.jpeg)
IK Rigノードの各Goalの設定は「Manual Input」にして、Position Spaceの設定は「Additive」にしています。
実装した結果はこちら：
![foot ik.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/761959a6-f81d-e71b-a035-852a829c7019.jpeg)
# 問題点
IK Rigの実装をABP_Mannyで実装してもデフォルトのBP‗ThirdPersonCharacterにIKを適用できなかった。
色々探した結果、どうやらIK Rigノードは継承されたアニメーションBPに正しく適用されないようです。
![animation BPs.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1786401/0255be27-06d6-d1bf-d7af-643bd1cb9a53.jpeg)
左側がIK Rigを実装したアニメーションBP、右側がそれを継承したアニメーションBPです。BP‗ThirdPersonCharacterはデフォルトで右側のアニメーションBPを設定している。ただし右側のBPは自分で一切ロジックを持っていなくて、AnimGraphで再生されるアニメーションをオーバーライドするためだけのBPのため、エンジン側の不具合の可能性が高いです。
現状はキャラクターのアニメーションBPを「ABP_Manny」に設定したら正しく動作してくれますのでそれで回避しています。

# 感想
IK Rigを使用してゲーム内のIKを実装してみましたが、コントロールリグで実装すると比べて計算処理をIKリグの内部で完結できないのが不便と感じました。
まだIK Rigはスケルトンを参照しているため、コントロールリグとは違って違うスケルトンの間での流用が難しいので、ゲーム内IKを実装する場合はスケルトンの構成によって複数のIK Rigを作成して複数のアニメーションBPにそれぞれ実装する必要が出てきます。
まだ前述した継承したアニメーションBPでの挙動の問題も含めて、採用できないケースもあると思います。

将来は期待できるかもしれませんが、現状でゲーム内のIKを実装するならコントロールリグの方がおすすめです。

# 参考資料
公式ドキュメント：https://docs.unrealengine.com/5.0/ja/unreal-engine-ik-rig/
HistoriaさんのIK実装チュートリアル：
https://historia.co.jp/archives/3421/
https://historia.co.jp/archives/3434/
https://historia.co.jp/archives/3518/
CloudFront → パブリックALB（Application Load Balancer）作成

## はじめに
今日は、CloudFront → パブリックALB（Application Load Balancer）を作成してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/1c0f253b-fd50-63c9-181d-234fa0799e55.png)

## 前提
CloudFrontを構築する前に、ALBとEC2を作成しました。
(参照: https://qiita.com/tannh/items/f1dbe7bfc2dca955fda4)

## 手順
#### 1. CloudFront作成
CloudFront Consoleで、[ディストリビューションを作成]を押して、次の手順を実行します。
(参照: https://us-east-1.console.aws.amazon.com/cloudfront/v3/home)

オリジンを設定します。
[オリジンドメイン]は、前の投稿で作成されたALBのカスタムドメインです。 
[プロトコル]は、CloudFront がオリジンに接続するときに使用するプロトコル (HTTP または HTTPS) を決定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/7bbda685-beed-2382-2c98-4464c2eab03d.png)

ビヘイビアを設定します。
[ビューワープロトコルポリシー]は、クライアントがHTTPを使用してアクセスする場合、CloudFrontはHTTPSにリダイレクトします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/6f2da02b-f3ce-7050-e023-d69dac990045.png)

動的コンテンツであるため、デフォルトではキャッシュは設定されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/1d2d1a2c-0d87-9702-d2f9-e55070dee405.png)

カスタムドメインとSSL証明書を設定します。
[代替ドメイン名]はCloudFrontのカスタムドメインです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/c4803fe9-9d2e-c31b-57bf-24ce50482825.png)

#### 2. Route53のDNSレコード作成
Route53でCloudFrontのカスタムドメインを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/24b9628d-8963-7af3-3e30-a25e9cd1efe5.png)

#### 3. キャッシュ動作の設定
上記のデフォルトの動作は、キャッシュ設定なしです。
[\*.jpg]、[\*.css] などの静的コンテンツのキャッシュを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/99618064-0421-7896-fcf8-8af46e9bb4ce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/8ac292e2-38bd-52b6-944f-27dd150f8ce3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/e02e856b-c010-de10-28b9-99c5ee67d4c2.png)

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/35775214-1a33-6dc1-025d-4b4a080bdc7b.png)

### ドキュメント参照
[Creating a distribution]
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-creating-console.html

[Values that you specify when you create or update a distribution]
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html
暗号化LVMをvgrenameしてrebootした時のエラー

# 環境
virtualbox 6.1.34
debian 11
# 前提
![スクリーンショット 2022-07-01 14.43.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655458/48a48607-9e72-9da2-b8d0-e6c78281e635.png)
"shshimad42--vg"という名前から"LVMGroup"にする。
```
vgrename shshimad42--vg LVMGroup
```
"/etc/fstab", "/boot/grub/grub.cfg"の中にある"shshimad42--vg"を"LVMGroup"に変更する。
# 本題
rebootしたら、まだ古いグループ名がある。
![スクリーンショット 2022-07-01 15.09.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655458/d468faac-6cf7-1fa9-eb8b-8778a78b3ff1.png)
/etc/initramfs-tools/conf.d/resumeをLVMGroup-swap_1に変更して、アップデートをする。
```
update-initramfs -u
```
無事に変更できた。
![スクリーンショット 2022-07-01 15.30.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655458/e3fd52c3-9089-242d-9ac7-94726ba9d883.png)
# 参考記事
https://unix.stackexchange.com/questions/625490/cryptsetup-error-couldnt-resolve-device-combined-with-cryptsetup-warning
AWSでMFA認証できなくなったこと


# なぜ起きたか
Google Atuhenticatorを入れたスマホを
引き継ぎを知らずに買い替えた。

後日、AWSにサインインしようとし、2段階認証を求められ
Google Atuhenticator　を開くと初期状態に戻っていた。

# 結論
公式のアナウンスに沿って手続きをすれば、サインインが可能。

ですが時間には余裕を持って。数時間〜半日、場合によっては1日分ほど。　

# これで困ったこと
ログインができなくなりAWSからの請求対象解除が遅くなった。

# 解決のために行ったこと
調べていると解決方法を記載したものがり、
最終的に下記のAWSのユーザーガイドにたどり着きました。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html

「ルートユーザー MFA デバイスの回復」の項目に沿って進めていく。
電話番号の確認　の箇所で登録してある電話番号はあるが、
次のエラーとなった。「電話の確認を完了できませんでした。」
![スクリーンショット 2022-06-30 17.56.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468139/633c3d39-53f4-e8f6-5f6d-f565161b7a2f.png)


こうなると仕方なく　”AWSサポートにお問わせください。”　リンクから
必要事項を記載し、サポートを依頼した。

数時間後に入電があったのですがタイミングが合わず、
サポート連絡から24時間が経ち二段階認証の解除が完了。
無事サインインできました。

# 参考
https://www.fenet.jp/aws/column/technique/1268/

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html
2進数の足し算と引き算　2進数の計算と数値表現

# コンピュータの得意な処理
コンピュータは足し算がとても得意。
回路を単純に保つため。

しかし
足し算は知っているが、引き算、掛け算、割り算は知らない。
コンピュータは工夫してそれ以外の計算を行なっている。

## 気づき
足し算以外知らないのは知らなかった。
どんな工夫をしているのか？
これから期待だ。

# 足し算しか概念がないコンピュータに引き算を理解させる。
足し算しか知らないので足し算で引き算を行う。
それは負の数を表現すること。
負の数で足すと引き算になる。

## 気づき
どうやって負の数を表現するのか？

# 負の数のあらわし方
最初の一桁が０の時　正の数
１の時　負の数
２進数で表された３と−３を足し合わせても０にはならない。
００００００１１＋１０００００１１＝１００００１１０になる。

そのために補数を使う。
それは```その桁数での最大値を得るために補う数```、```次の桁に繰り上がるために補う数```という２つの補数がある。

## 気づき
そもそも補数は必要なのかうまく想像できない。
補数は計算を完了させるために設けられていると思っている。
１０進数の場合は補数は要らないのかな？
負の数を表すために一桁で表すからどうやって引くのか？
そうか負の数を作るための補数なのか。

## １０進数の補数の場合
### 桁数での最大値を得るために補う数（１２３の場合)
９９９から１２３を引けばその数の補数を得ることができる。
これを９の補数
### 次の桁に繰り上がるために補う数（１２３の場合)
１０００から１２３を引けばその数の補数を得ることができる。
これを１０の補数
## ２進数の補数を求める(これが問題だ）
0011これは３を意味する。
この桁の最大値は１１１１になる。
そこから１１１１から００１１を引くと１１００になる。(これが１の補数になる）

一桁上げるための補数
１００００から００１１を引くと１１０１になる。（これが２の補数になる）

00000011(3)+11111101を足すと１００００００００になる。
８ビット部分だけをみれば全部０になる
```負の数を表すには２の補数で表す```。

## 気づき
なんか８ビットだけをみると０になると説明されてもわからないが
こう表現されるのであれば仕方がない。
理解はできないけどこうなるのなら覚えよう。
２の補数は負の数
【Swift】アプリのバージョン情報を表示

# はじめに
アプリ内でこのような表示を見たことはありませんか？
![IMG_0579.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2b9c3adb-a88c-04ea-e81e-96f0a555e093.jpeg)
これはXcodeで設定できるIdentityのVersionとBuildで構成されているアプリのバージョン情報です。
![スクリーンショット 2022-07-01 15.16.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3539297f-cb5c-83ce-1d35-bb4caf84721f.png)

バージョンの設定をどのように取得するのでしょうか

今回はやり方を紹介します

# 方法
## Version
```swift
var version: String {
    guard let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String else { return "" }
    return version
}
```

## Build
```swift
var build: String {
    guard let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String else { return "" }
    return build
}
```

# 使い方
![Simulator Screen Shot - iPhone 12 - 2022-07-01 at 15.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8abdec28-cd4f-ceb0-cca9-4b0e51e0e268.png)
```swift
import SwiftUI

struct ContentView: View {
    var version: String {
        guard let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String else { return "" }
        return version
    }
    var build: String {
        guard let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String else { return "" }
        return build
    }
    var body: some View {
        List {
            HStack {
                Text("バージョン")
                    .fontWeight(.bold)
                Spacer()
                Text("\(version)(\(build))")
                    .foregroundColor(.gray)
                    .fontWeight(.regular)
            }
        }
    }
}
```
DateTime型のフィールドのフォーマット(データローダー)


データローダで日時型のフィールドを使う時の注意。

言語は英語ですが、時間は日本時間にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cefb5f6a-9572-9f0c-4b3d-c0193bec8b97.png)

ZをつけるとGMT( UTC )になります。そのため環境が日本時間なので+9の表示になります。

何もつけない時もどうもZと同じ扱いですね。

+09:00とすると、日本時間で追加されるようです。　そのため正しく 00:00:00ということで 12:00 AMになっています。

-09:00:00 とすると本来は9:00なりますが、日本時間になっているので、更に +9時間で 18:00になっています。
Linuxのストリーム、パイプ、リダイレクト

# リダイレクト
***データの出入力先を変更すること***です。

## リダイレクト使い方
```
$ ls > ls.txt
#ファイル一覧を出力　出力先は(上書き保存)　ls.txt

$ ls >> ls.txt
#ファイル一覧を出力  出力先は(上書き保存)　ls.txt

$ cat <  ls.txt
#入力されたファイル内容を表示　入力元は　ls.txt
```


# リダイレクトの種類

![スクリーンショット 2022-07-01 13.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/1e483367-2b80-d2c1-e500-a022c3848117.png)

>引用　　https://eng-entrance.com/linux-redirect


# パイプ
コマンドやプログラムの実行結果を、他のコマンドやプログラムの入力として利用することです。

## パイプ使い方
```
$ ls |wc
# ファイル一覧出力　　出力結果を右のコマンド入力として利用　行数を出力
```


# teeコマンド
標準入力から受け取った内容を、標準出力とファイルに書き出すコマンドです。ファイルへの保存と標準出力への出力を同時に行ったり、複数のファイルに出力したりすることができます。
```-a```で***ファイルに上書き保存ではなく追加保存***します。

```
$ ls |tee ls.txt | cat
# ファイル一覧出力　　結果を出力し、ファイルに書き込む　→ 保存先はls.txt
```

https://atmarkit.itmedia.co.jp/ait/articles/1611/16/news022.html#:~:text=tee%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A8%E3%81%AF%EF%BC%9F,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82


# xargsコマンド
文字列をコマンドの引数としてコマンドを実行します。```-a```ファイルに上書き保存ではなく追加保存します。

```
$ ls | xargs cat
# ファイル一覧出力　　受け取った結果を指定したコマンドの引数　指定したコマンドはcat
```


# 資料

https://www.udemy.com/course/linuc-lv1-101/

https://qiita.com/progrhyme/items/e99be732c2e62d4a7641

https://qiita.com/kannkyo/items/2835f6eac3a58a68ad37
最近Windowsエクスプローラーが落ちるので代わりのファイルマネージャーを使ってみる

こんにちは、社会人です。

最近、エクスプローラーの調子がとても悪く頻繁に強制終了してしまいます。
原因も調べてみましたが私のミニマム脳みそでは、解決方法がよくわからないので新たにファイルマネージャーを入れて使おうと思います。

そこまでソフトウェアにこだわりは無いので、Google先生に「ファイラー　おすすめ」で調べてもらい見かけた「As/R」というファイラーを使ってみたいと思います。

普段データの管理は「Box」で行っており「Box Drive」を使ってエクスプローラーからデスクトップで操作をしてデータを開いていますが、「As/R」で「Box Drive」を開くことが出来るのか、残念ながらさっぱりわかりません。

見れたら嬉しいです。
さっそくインストールしました、やり方はソフトの提供元の「AMA Soft」さんが丁寧に書いてくれているので私でも出来そうです。

と、喜んでいるのもつかの間、残念なことに「Box」ないし「Box Drive」の連携については書かれておらず調べてみましたがそれらしき内容も書いておらず、どうやら連携は難しいのかもしれません。

引き続きエクスプローラーに代わるファイルマネージャーを探す旅は続きます。
なにか良いことがあればまた記事にしようと思います。
WordPressが乗っ取られた話

ある日いつもどおりサイトのアクセスを調べてみると、ほぼアクセス0の状態に…

「何が起きたんだ？」と思い調べてみると、どうやらサイトが改ざんされ、私のサイトが表示されていないようだ。
<h2>ことの端末は不正アクセスから</h2>
私のサイトはWordPressで運営しており、一応ログインすると通知来るように設定してある。

通知メールを調べてみると、深夜にログイン失敗の通知が来ており、その20分後にログインされている。

まず放置しているサイト『<a href="https://naruhodo-net-news.com/">ナルニュー</a>』にログインされサイトを改ざんし、同じサーバーにある『<a href="https://kingsmor.com/">キングスモー</a>』も同じく改ざんしたようだ。
<h2>自分でどうにかしてみたが、どうにもならず</h2>
まずサイトが改ざんされた事をサーバー側に報告すると、返答は取り敢えずサイトにアクセス制限かけたから、「復旧したら報告してね」とのこと。

よく分からないまま対応すべく自分で調べてみると、どうやらhtaccessの記述が変更され、見覚えが無いファイルが追加されているようだ。

まずhtaccessの記述を元に戻してみたが、改ざんされたhtaccessの記述になってしまう、ファイルも消してみたが、更新をするとまたファイルが復活するようだ。

面倒だが、もうWordPressを一度まっさらにし、バックアップから復旧するしかなさそう…そこで、サーバー側の自動バックアップをしていることを思いだした。

どう考えても、私が始めて復旧するより、サーバー側で改ざんされる前に復旧した方が簡単で確実だ。

そこからは早かった。ちょうど丸一日ほどで、復旧して貰えた。

あとは、ログインページを変更し、ログインパスワードを複雑にすれば、取り敢えず完了。
IDでテーブルを結合する 部分外部結合と逆結合(SPSS Modeler データ加工逆引き6-2)

# IDでテーブルを結合する（部分外部結合と逆結合）

![スクリーンショット 2022-06-30 14.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/23117d64-4225-e3d4-fd9c-7caee0700097.png)

＊内部結合と完全外部結合はデータ加工逆引き6-1をご覧ください。

## 1.想定される利用目的

・レコメンド用商品テーブルの作成
・異常検知のアラートリストの作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/outer_join.str?raw=true

## 3.サンプルストリームの説明
![スクリーンショット 2022-06-30 17.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/babf9c90-1510-07bf-4a83-a22db6bab07d.png)

a.入力するデータひとつ目は以下の通りです。
![スクリーンショット 2022-06-30 14.47.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bd39a235-9d24-d4d6-ff15-dc1d58bb2834.png)

b.入力するデータ２つ目は以下の通りです。
![スクリーンショット 2022-06-30 14.47.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/268cf6fd-ce9e-9aa3-32a6-cacc9713bc8d.png)

#### 部分外部結合(partial outer join)

c.[レコード結合]ノードを編集します。[レコード結合方法]を[キー]にして[会員ID]を[結合キー]にします。ラジオボタンは[一致レコードおよび選択した不一致レコードを含める（部分外部結合）]を選択します。[データの選択]ボタンを押して[果物購入者リスト]が主テーブルになっていることを確認します。
![スクリーンショット 2022-06-30 17.35.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/910e99a5-e673-fea3-231f-21a72646231e.png)


[プレビュー]をします。果物購入者のを主として野菜購入の列が追加されました。該当がない場合には欠損値Nullが割り当てられています。
![スクリーンショット 2022-06-30 17.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b4a99324-93f1-8241-0adc-ef776a8a0f13.png)

#### 逆結合(anti-join)

d.[レコード結合]ノードを編集します。[レコード結合方法]を[キー]にして[会員ID]を[結合キー]にします。ラジオボタンは[最初のデータセット中の他と一致しないレコードを含める（逆結合）]を選択します。
![スクリーンショット 2022-06-30 17.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a96cfc59-d948-a00e-1afc-a0e6d834ec8d.png)

[プレビュー]をします。野菜を買っていない果物の会員リストが作られました。
![スクリーンショット 2022-06-30 17.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/eb4c70b7-d580-1623-9220-869e4454cf9e.png)

#### 注意事項

会員IDは整数か文字列で統一している必要があります。また片方のフィールド名称が会員番号だった場合にはあらかじめ[フィルター]ノードで会員IDにリネームしておきます。

## 4.参考情報

#### [レコード結合]の解説記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-13/

https://qiita.com/416nishimaki/items/be61a82c12cd83558def


#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008