OmniAICreator/Qiita-1.07M huggingface dataset:
straight skeleton (scikit-geometry 利用)

こんにちは。
[straight skeleton](https://en.wikipedia.org/wiki/Straight_skeleton) を描きました（下図内の赤線）。[scikit-geometry](https://scikit-geometry.github.io/scikit-geometry) を利用しています。

用途として、例えば河川の両岸形状を与え、その中心線を求めるなどです。

<img width="300" alt="skeleton" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/0db93b31-2527-2949-b249-1d1da04618c9.jpeg">

```console
$ brew install cgal pybind11 python3
$ pip3 install matplotlib
$ pip3 install git+https://github.com/scikit-geometry/scikit-geometry.git
$ ./skeleton.py
```

```skeleton.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import skgeom as sg
from skgeom.draw import draw
import matplotlib.pyplot as plt

def draw_skeleton(polygon, skeleton, show_time=False):
    draw(polygon)
    if skeleton:
        for h in skeleton.halfedges:
            if h.is_bisector:
                p1 = h.vertex.point
                p2 = h.opposite.vertex.point
                plt.plot([p1.x(), p2.x()], [p1.y(), p2.y()], 'r-', lw=2)
        if show_time:
            for v in skeleton.vertices:
                plt.gcf().gca().add_artist(plt.Circle(
                    (v.point.x(), v.point.y()),
                    v.time, color='blue', fill=False))

poly = sg.Polygon([(0, 0), (4, 2), (8, 1), (8, 3), (4, 5), (0, 2)])

skel = sg.skeleton.create_interior_straight_skeleton(poly)
draw_skeleton(poly, skel, show_time=True)

plt.show()
plt.close()
```
Next.jsでSSR中にファイルを触ってはいけない

Next.jsでSSR中に`fs`を触ったらエラーが起きたので整理しておきます。

# Next.jsのレンダリングの方法

Next.jsがサーバーサイドでページをレンダリングする方法にはSSG (Static Site Generation), SSR (Server Side Rendering), ISR (Incremental Static Regeneration), SSG (fallback)などがあります。

## SSG

ビルド時にサーバーサイドでページをレンダリングします。動的パスの場合は`getStaticPaths`でパスを指定します。

## SSR

リクエストがあったときにサーバーサイドでページをレンダリングします。

## ISR

`getStaticPaths`で`revalidate`を指定すると適用されます。リクエストがあったときは静的なページを返しますが、`revalidate`で指定した期間が過ぎていたら裏で再度レンダリングします。

## SSG (fallback)

`getStaticPaths`で`fallback: true`を指定すると適用されます。ビルドされていないページのパスにリクエストが来たら、その場でページをレンダリングします。

# Next.jsのサーバーサイド環境は2つある

## ビルド環境

`next dev`, `next build`, `next start`などが動いている環境です。`getStaticPaths`で指定されたページのレンダリングは常にこちらで行われます。

ここではプロジェクトに含まれるすべてのファイルにアクセスできます。

自前のサーバーやコンテナ、Herokuなどで`next start`で動かしている場合は常にビルド環境になります。

## [サーバーレスモード](https://nextjs.org/blog/next-8#serverless-nextjs)

`next.config.js`で`target: 'serverless'`が指定されていると、ビルド時にページごとに単一のjsファイル (lambda) が生成されます。SSR, ISR, SSG (fallback)など、リクエスト時のレンダリングはこのlambdaを動かすことで行われます。

[Vercelのドキュメント](https://vercel.com/support/articles/how-can-i-use-files-in-serverless-functions)に書かれているように、原則としてlambdaからはファイルシステムにアクセスできません。[webpackの設定をいじれば](https://github.com/vercel/next.js/issues/8251#issuecomment-854148718)できないことはないですが、基本的にハックの範疇なので将来的に動かなくなる可能性があります。`pages/api/`の下にあるAPI Routesについても、同じくファイルシステムは触ってはいけません。

サーバーレスモードはVercelやNetlifyで適用されます。

## ビルド環境かサーバーレスモードかを判定するには

Vercelの場合は環境変数に`CI=1`が設定されていればビルド環境、されていなければサーバーレスモードです。Netlifyについては把握していませんが、少なくとも自前で環境変数をセットしておけば判定できると思います。

## サーバーレスモードからファイルにアクセスするには

まずはSSRでなくSSGで対応できないか、リソースをlambdaに含められないかを検討しましょう。JSONを読みたい場合は`fs`から読まずに`import`するなどの方法があります。

どうしてもSSR中にファイルを読みたい場合はネットワークからフェッチする必要があります。`public/`かS3などのストレージに置きましょう。

# まとめ

VercelやNetlifyにデプロイされているNext.jsアプリケーションで、ビルド中以外にファイルシステムを触ってはいけない。
AOJトライに関する知識知見の記録共有 （Volume0-0041）

# 概要
Expression

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0041
 
# コード
TIPS：再帰処理により可変長引数に対応

```
import itertools

def apply_op(op, args):
    a, b = args[:2]
    if op == "+":
        return a + b
    elif op == "-":
        return a - b
    elif op == "*":
        return a * b

def gen_list_histresult(hist, args):
    if len(args) == 1:
        return [[hist, args]]
    else:
        ret = []
        for v in itertools.permutations(args):
            for op in ["+", "-", "*"]:
                new_valuelist = [apply_op(op, v[:2])] + list(v[2:])
                ret.extend(gen_list_histresult(hist + [op, v[:2]], new_valuelist))
        return ret

def ret_readable_exp(v):
    return v

def core(args, cond_res=10):
    list_hist_valuelist = gen_list_histresult([], args)
    print(len(list_hist_valuelist), list_hist_valuelist[0])
    return [[ret_readable_exp(v[0]), v[1]] for v in list_hist_valuelist if v[1] == [cond_res]][:1]

def app(*args):
    return [[arg, core(arg)] for arg in args]

print(app(
[8, 7, 9, 9],
[4, 4, 4, 4],
[5, 5, 7, 5],
[1, 2, 7],
))

```

# 実行結果
デバッグログ出力部含む

```
7776 [['+', (8, 7), '+', (15, 9), '+', (24, 9)], [33]]
7776 [['+', (4, 4), '+', (8, 4), '+', (12, 4)], [16]]
7776 [['+', (5, 5), '+', (10, 7), '+', (17, 5)], [22]]
108 [['+', (1, 2), '+', (3, 7)], [10]]
[[[8, 7, 9, 9], [[['-', (9, 7), '*', (2, 9), '-', (18, 8)], [10]]]], [[4, 4, 4, 4], []], [[5, 5, 7, 5], [[['*', (5, 5), '*', (7, 5), '-', (35, 25)], [10]]]], [[1, 2, 7], [[['+', (1, 2), '+', (3, 7)], [10]]]]]
```
ローカルのファイルをGithubのリポジトリにアップロードする方法

# はじめに
node.jsの勉強を始めたのですが、ローカル上で作成したソースをGithubでのリポジトリ管理したいなと思い、その方法をまとめました。

# ローカルファイルをGithubへ
ここでは、コマンドでアップロード（リモートのリポジトリに関連付け）する方法になります。

①最初に、アップロードするルートディレクトリに移動します。

```
cd ソースのルートディレクトリ
```

②gitリポジトリを新規作成します。

```
git init
```
③gitでバージョン管理する対象を追加する

```
git add .
```

④コミットします。-m はコミットメッセージを付けるためのオプションです。mはmessageのmです。

```
git commit -m "コメント名"
```

⑤ローカルのリポジトリをGithub上のリモートリポジトリ上に紐づけします。

```
git remote add origin リモートリポジトリURL
```
※リモートリポジトリURLはgithubのリポジトリ画面から取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249795/be72a85b-2144-9f60-8886-7a56d5efcbf8.png)


⑥Github上へアップロード（プッシュ）します。

```
git push -u origin main
```

# 終わりに
Github上でリポジトリを作成した直後に、上記で整理した手順が丁寧に書いてあることに気づきました・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249795/8d1a1cfc-7904-9ccc-f725-9d99c950bce5.png)
さすがGithubですね。気が利きます。
【Sfdx/Apex】パッケージ開発時の「In field: apexClass - no ApexClass named HogeClass found」と向き合う

# 概要
SalesforceのAppExchangeアプリの開発時、スクラッチ組織へのソースプッシュ時に起こる`In field: apexClass - no ApexClass named HogeClass found`の対策方法

対象の読者の方は
- パッケージ開発をされている
- スクラッチ組織やxml形式のメタデータ、Gitの知識がある
- 上のエラーが出て困っている

以上です。よろしくお願いします。

## エラーの経緯

結論を述べる前に経緯を書きます。

あるスクラッチ組織で開発をしていたのですが、30日の期限の中で開発が間に合わなかったので、ソースをブランチで管理したまま、スクラッチ組織を作り直そうと思いました。

プロファイルやカスタムオブジェクトなど、さまざまなメタデータの変更点はあったのですが、`sfdx force:source:pull`を行い、基本的な変更点はバージョン管理してから作り直しました。

mainブランチのコードでスクラッチ組織を作り、ブランチを切り替えてから`sfdx force:source:push`をしたところ、掲題のエラーが出たというわけです。

### 調べてみる

一度削除して該当クラスを作り直す方法と、設定＞開発からコンパイルする方法がありましたが、そもそもスクラッチ組織にソースをプッシュできていないので、関係なさそうでした。

## 解決方法

アテをつけて色々やってみたところ、以下の方法で解決しました。

**.forceignore**に以下のコードを追加

```:.forceignore
**/profiles/**
**/appMenus/AppSwitcher.appMenu-meta.xml
```

この状態で`sfdx force:source:push`を実行。

その後、追加したコードを削除して`sfdx force:source:push`を実行。

以上です。

### 考察
エラーの詳細を読むと、プロファイルとAppSwitcherが新規作成したApexクラスを探せていないようでした。
ここで、自分で当てをつけて「先にクラスプッシュすればいけるんじゃね…？」と思って試したらいけた感じです。

あくまで推測の域を出ませんが、コンパイルの順序を考えたときに、基本はプロファイルから行われるからこのようなことが起こるのかなーとか考えました。

また余裕がある時に調べてみます。

#### その他
Salesforceのパッケージ開発にご興味がある方は、採用やっているのでぜひ来てください！
Apexの経験やSalesforceの経験があれば嬉しいですが、Javaなどの経験でも大歓迎です！

カジュアル面談もやってるのでぜひ〜

https://www.wantedly.com/companies/company_3244501
Android12のFCM対応問題

# 背景

Flutter1.xでアプリを開発しました。

運営でAndroid12を対応しないといけないため、色々苦労しました。

Firebase Clound Messaging(FCM)の対応は一番しんどいでした。

Android12ではServiceに対して、exportしないといけない

# export対応

[こちらのGoogle先生のドキュメント](https://developer.android.com/about/versions/12/behavior-changes-12?hl=ja)によると

FCMのServiceはFirebaseMessagingServiceなので、`export=false`かと思います。

そして、この後はビルド成功し、特に問題なかった。

リリース審査出す直前、まさかの通知不通のテスト結果出て、exportの影響だなぁと思いきや、他の問題でした。

# 問題

前提：
FCMの20.0.0を使用しています。

現象:
Android12のセキュリティ対応によって、こんなエラー出ていました。
```
Targeting S+ (version 10000 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
```

しかも、直接crash、やばいですね。

ログを追った結果。

```
android.app.PendingIntent.checkFlags(PendingIntent.java:375) at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645) at android.app.PendingIntent.getBroadcast(PendingIntent.java:632) at
com.google.firebase.a
com.google.firebase.b
com.google.firebase.FirebaseMessagingService
com.google.firebase.h
com.google.firebase.g
```

結論:
firebase悪いのだ。
中にPendingIntentする時が、FlagはFLAG_MUTABLEして、`onMessageReceived`を呼べなくなっている、ってか、crashしていた。

# 対応
firebase悪いので、firebaseのバージョンを上がるしかない（下がるのはないでしょ、Android12だぞ、最新だぞ)。

最後は`com.google.firebase:firebase-messaging:21.1.0`で安定しました。

firebaseのandroid sdk仕様は近年すごく変更して、まとめにならないですね。

確かに、firebase-coreからfirebase-バラバラになっている。
しかも、バージョンはバラバラのリリースの番号になっています、開発者として管理難しいと思いますが。
みんな様どう思うでしょう。

# 最後
本文書く目的として、
自分は今日FCMに関して、一個一個試して、結果を探すしかないなので、
時間のロスしないように、共有いたしました。

みんな様のAndroid12対応の道に役に立つ様に祈ります。
Swift 　??について復習

#今回の内容

* `??`とは何かについて復習する為の内容です。 

#コードと簡単解説

* 宣言した`testString`が`nill`のまま`print()`内で使われた為、`testString ?? "nillでした"`の`"nillでした"`の部分がprintされる様になります。

```Swift:

    var testString:String?
    
    override func viewDidLoad() {
        super.viewDidLoad()       
        
        print(testString ?? "nillでした")    
    }
```

```:print結果
    nillでした
```

* `testString`に値が入ったので、`print()`される値は`testString`が表示されます。

```Swift:

    var testString:String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        testString = "nillじゃなーーーーーーーーい"
        
        print(testString ?? "nillでした")
    }
```

```:print結果
    nillじゃなーーーーーーーーい
```

# まとめ
対象の値が`nil`の場合に`??`以降の値を使って処理が働きます。

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
【Kotlin】ByteArrayを無限に連結したい

# やりたいこと

[【Java】Byte配列を無限に連結したい](https://qiita.com/hyuta/items/943492c568d8c8614bee)
のKotlin版。ByteArrayを無限に連結できる1つの関数が欲しい。

# 追記
コメントいただきましたがreduceであっさりできますね。ありがとうございます。

```Kotlin
fun concatArrays(vararg arrays: ByteArray): ByteArray =
    arrays.reduce { acc, cur -> acc + cur }
```

# 結果
可変長引数で順にPlusすることでひとまず実現。Kotlinの可変長引数はArrayに格納されているため下記では
```arrays```は```Array<ByteArray>```となる。もっとスマートな方法もありそう。

```Kotlin
fun concatArrays(vararg arrays: ByteArray): ByteArray{
  var result = byteArrayOf()
  arrays.forEach { array ->
      result += array
  }
  return result
}

fun main(args: Array<String>) {
  val v1 = byteArrayOf(1, 2)
  val v2 = byteArrayOf(3, 4, 5)
  val v3 = byteArrayOf(6, 7, 8, 9)
  
  println(Arrays.toString(concatArrays(v1)))
  println(Arrays.toString(concatArrays(v1, v2)))
  println(Arrays.toString(concatArrays(v1, v2, v3)))
}
```

Output

```
[1, 2]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```
OfficeScripts: WebExcelでブレストした際の羅列キーワードをまとめる

# 背景
デザイン思考関連講義を受けた際、ブレストでキーワードを大量に出して、それを親和図法に利用する。ということをした。
この際、Web 版 Excel を利用したわけだが、キーワード羅列を A 列に手コピペしてたので・・。

単発なら VS Code とかで、正規表現置換する方が簡単ですけどね

|置換対象|置換後|
|-|-|
|[\n\t]+|\n|

# 動作イメージ
![getValues.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e4b8c85e-98b0-2fc3-6685-9356e65ea41a.gif)

# コード
```typescript:範囲内の値を一列にまとめる
function main(workbook: ExcelScript.Workbook) {
	let selectedSheet = workbook.getActiveWorksheet();
	// Set range D3 on selectedSheet
	var values = selectedSheet
		.getUsedRange()  // or .getRange("A1:H20")
		.getValues()
		.reduce((a, b) => { a.push(...b); return a }, [])		// 二次元 to 一次元
		.filter(f=> f != "")		// 空の排除
		.map(m=> m.toString());

	// 一覧の記入。二次元配列化して、SetValues 出来たらそのほうがよさそう
	var rowNumber = 1;
	values.forEach(f =>
		selectedSheet.getRange("J" + rowNumber++).setValue(f)
	);
}
```

# 心残り
1. SetValues(string[][]) で一気に書き込みたかったけど・・面倒だったので・・
WindowsインスタンスにEBSボリュームをアタッチした際の初期処理をPowerShellでやる

Windowsでディスクを追加した場合、ディスクの初期化したりドライブレターをつけますが、今回はこの作業をPowerShellだけで実施してみます。

画面操作で対応する場合の、AWSドキュメントとしては下記参照。

[Windows で Amazon EBS ボリュームを使用できるようにする](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ebs-using-volumes.html)

## 今回用意した環境

`Windows Server 2019` に10GBのEBSを追加ディスクとしてアタッチして初期化を行う。

今回用意したEBS　vol-0df8055a84348b95d。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/0df94461-ce69-15df-76c8-b1cc4fbd4cc6.png)

## ディスクがアタッチされているか確認する

[EBS デバイスの特定](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/nvme-ebs-volumes.html#identify-nvme-ebs-device)

`WindowsServer 2008 R2` 以降ならば `ebsnvme-id.exe` を利用してボリューム情報が簡単に取得できます。

`"C:\ProgramData\Amazon\Tools\ebsnvme-id.exe"`にインストールされていない場合は、上記AWSドキュメントからダウンロードしてバイナリを適宜配置して実行して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/ad8176fa-388e-5884-d1b6-bd79216f840a.png)

`ebsnvme-id.exe`を実行した結果、今回用意した、`vol-0df8055a84348b95d`が`Disk Number 2`としてアタッチされている事がわかります。

## アタッチされたディスクの初期処理

下記は`vol-0df8055a84348b95d`が`Windows`に`Disk 2`アタッチされている環境でドライブレターを`Wドライブ`としてドライブラベルを`WORK`としています。

```PowerShell:PowerShellで初期処理
# 

# ディスクの状態を確認
# 対象のディスクがオンライになっているかどうか
Get-Disk -Number 2

# ディスクがオフラインの場合はonlineにする
Get-Disk -Number 2 | Set-Disk -IsOffline $false

# アタッチした　Number 2　のディスクを GPT形式で初期化
Get-Disk -Number 2 | Initialize-Disk -PartitionStyle GPT

# パーテーションの設定
Get-Disk -Number 2 | New-Partition -UseMaximumSize -DriveLetter W

# フォーマット
Format-Volume -DriveLetter W -FileSystem NTFS -NewFileSystemLabel 'WORK'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/13f0962c-ff1e-0f1e-95ce-6e5e4f5dd9dd.png)

## おまけ

指定したドライブをオフラインにする場合は下記のように指定できます。

```PowerShell
# W ボリューム`をオフラインにする場合
Get-Volume -DriveLetter w | Get-Partition | Get-Disk | Set-Disk -IsOffline $true
```

# 総評

特に難しい部分もなく、処理が出来るかと思います。　また手順等に組み入れる場合は、やはりコマンドのほうが便利かと思います。
Teams Webhook 特定の条件下で起きたエラーにハマった

社内で定期実行しているPoweshellスクリプトがあって、TeamsのWebhookで通知を飛ばしたりしているんだけど、2021年10月下旬あたりからいきなり通知がこなくなったので、その調査記録をここに残す。

# ローカルユーザーで実行するとエラーになる。
まずスクリプトの実行環境は以下の通り。

 - Network: 社内LAN（AcriveDirectoryあり）
 - 実行環境: Windows Server 2016
 - PSVersion: 5.1.14393.4583

普段はタスクスケジューラで定期実行しており、どのようなエラー（標準エラー出力）を吐いているのか全く把握できないので、まずはPoweshell上でスクリプトを実行してみた。**因みにこの時はドメインユーザーで実行。**
実際動かしてみると、エラー出力されずスクリプトが終了し、Teamsにもちゃんと通知が届いた。
「ん？？ちゃんと動くじゃん。。」

今度はタスクスケジューラを手動実行してみた。
タスクスケジューラ自体は正常に終了したが、やはりTeamsに通知が来ない。。

ここでタスクスケジューラを実行するユーザー（**ローカルユーザー**）に注目し、ローカルユーザーでスクリプトを実行してみた。そしたら`Invoke-RestMethod`コマンドで以下エラーが吐き出された。

```Powershell
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At C:\filename.ps1:74 char:1
+ Invoke-RestMethod -Uri $WebHookURI -Method Post -ContentType 'applica ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

```

上記エラー内容を見ても正直原因追及ができず、そもそもなぜローカルユーザーだけいきなり使えなくなったんだ？プロファイル環境に依存なのか？

とりあえずこの日は**ローカルユーザー環境で起きる**ことがわかったので、一旦終了した。。

# 原因はTLSのバージョン？
とりあえずエラーメッセージを検索窓にそのまま貼り付けてみたらPowershell の default の TLS 1.0利用しようとしてエラーを吐いているのでは？という英語の記事を見つけた。
記事の内容とおり以下コードをスクリプトファイルに追加してみたら、ローカルユーザーでもTeamsにWebhook通知が届くようになった。

```Powershell
Set-ExecutionPolicy Bypass -Scope Process -Force
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
```

ドメインユーザー、ローカルユーザーのPowershell 上の既定のTLSの値は同値（SSL3、TLS(1.0)）なのに
なぜローカルユーザーだけエラーが起きてしまうのは正直謎のまま。。

もっと原因特定できたら追記します。🙇‍♂️🙇‍♂️
Error: Unknown command: prune

# 事象 : デッドシンボリックリンクを削除しようとしたらコマンドがないと言われた
```zsh
# 「linkできてない」とお医者さんに言われたので
$ brew doctor 
#...省略...
Warning: You have unlinked kegs in your Cellar.
Leaving kegs unlinked can lead to build-trouble and cause formulae that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  python@3.9

# unlinkして、
$ brew unlink python@3.9  
Unlinking /usr/local/Cellar/python@3.9/3.9.7_1... 3 symlinks removed.

# ディレクトリを消して
$ rm -drf /usr/local/Cellar/python@3.9 

# デッドシンボリックリンクを削除・・・できない
$ brew prune
Error: Unknown command: prune
```

## 原因 : `brew prune`は`brew cleanup`の一部になったから
> brew prune has been replaced by and is now run as part of brew cleanup.
> [1.9.0 — Homebrew](https://brew.sh/2019/01/09/homebrew-1.9.0/)

### 対応 : `brew cleanup`する
```zsh
$ brew cleanup
Pruned 2 symbolic links from /usr/local
```
ビデオ会議中、家族が部屋に入ってきて映り込んだー！を解消

##作ったもの
- 部屋に入る前にWebカメラがONになっているか確認する仕組み
- (Windowsでしか動きません。ごめんなさい。)

## 使い方

- (部屋のドアにはったNFCにスマホをかざす)  OR  (部屋のドアに貼ったQRコード[URL]をスマホで読み込む)
- WebカメラがONになっているか否かがスマホの画面にでる

## 使ったツール
1. Python (Flask, winreg)
1. ショートカット（iOS)
1. NFC
1. QRコード

## 仕組みの大枠
1. Webカメラを使うPC上で、PythonのWebサーバーを立てる（IPアドレスは固定しておく)
1. 部屋に貼ってあるNFCもしくはQRコード読み込んで、PCのWebサーバーにアクセス
1. Pythonで、レジストリを読み込み、Webカメラがオンになっているかを判定した結果を返す


## 作り方
- python環境にFlaskを入れる

```bash
pip install Flask
```

- [こちらのスクリプト](https://gist.github.com/KODOMOTO/7707e876ca9cebca647b0cd0db8662b4#file-eknockserver-py)を作成
- PC起動時にスクリプト自動実行するための設定
    - 作成したスクリプトを実行するbatファイルを作成　[こちら参照](https://qiita.com/Rujuu_study/items/01325c47d9eef70b6e89)
    - 起動時に実行するようスタートアップフォルダにバッチのショートカットを登録　[こちら参照](https://support.microsoft.com/ja-jp/windows/windows-10-%E3%81%AE%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B-150da165-dcd9-7230-517b-cf3c295d89dd)
- NFCまたはQRコードを使って、(PCのURL):8080/eKnock/　にアクセス
    - NFCをiPhoneで使いたい場合は、[こちら](https://qiita.com/quantum_cpa/items/6e85b3e102599893e252#%E4%BD%9C%E3%82%8A%E6%96%B9)の手順7.参照
    - QRコードの作り方は[こちら参照](https://qiita.com/quantum_cpa/items/2b50b0167f73252a7233#qr%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9)

## こぼれ話
- 実際に家で稼働させているものは、Webカメラがオフでも、PC画面に確認プロンプトを出して、入っていいか悪いか選べるようにしたり、LINE notifyを使って、LINEに通知したり、Flaskのテンプレートエンジン使ったりしているが説明が長くなるので、シンプル版を公開
- PC画面に確認プロンプトを出す部分は、Flaskからpyautoguiのconfirmを動かしたら、以下のエラーが出てコケた。

```
Tcl_AsyncDelete: async handler deleted by the wrong thread
```

- Threadを利用して回避できるかなと思ったけどうまくいかず、あきらめてSeleniumを起動して、Raspberry Piのnod-redで立てた、http serverにアクセスして... とかなり分かりにくい仕様に。いつか、きれいになったら公開しよう
Udemy「ネットワークエンジニアを目指す初心者はここから始めよう！「ゼロから学ぶネットワーク基礎」1028 ネットワーク インフラエンジニア

通信の流れを理解するために意識したいポイント
・同一ネットワーク宛か（直接通信or他機器に依頼）
・ARP解決は必要か（エントリーに期限がある）
・L2スイッチはMACアドレスを学習しているか
・ルータはルーティング情報を学習しているか
・IPアドレスはEnd-toEndで変わらないがMACアドレスは書き変わる



①通信相手が同じネットワークの場合は直接通信ができるが、異なるネットワークにいる場合はルータに転送してもらう必要がある。

②MAC アドレスを調べるために送信するのがARP Request、それに応じてMACアドレスを伝えるのがARP Replyである。

③L2 スイッチは受信したEthernet フレームの送信元MACアドレスから学習し、宛先MACアドレスから送信先を判断する。

④ルータやL3 スイッチでは同じ宛先に対して複数の経路がある時はLongest Prefix Match、Distance、Metricの優先順位で選択する。




サブネットマスクからネットワーク部とホスト部の境目を見つける方法
・（例）サブネットマスク:255.255.255.244を二進数に変換
→11111111.11111111.11111111.11100000になる。
※連続して1の部分がネットワーク部、連続して0の部分がホスト部になる。
Docker(windows)に割り当てるコア数を増やして実行速度を爆速にしたい

## 背景
- [マルチエージェントシミュレーション](https://mas.kke.co.jp/about/)を自作してDocker上で動かしているものの、あまりにも遅いから改善したい

## 環境
- windows10
- Docker(windows)

## 手順
1.wsl2がインストールされいることを以下のコマンドで確認

```terminal
wsl -l -v
```

2.`.wslconfig`ファイルを`Users/[ユーザープロファイル]`に作成

``` terminal
# power shellでディレクトリを「Users/ご自身のユーザ名」に移動してから実行
NewItem .wslconfig -type file
```

3.エディタでコア数を変更する (.wslconfig)

``` 
[wsl2]
processors = 5 #自身の環境に合わせて慎重に
```

4.wslを一旦shutdownする

```
wsl --shutdown
```

5.Dockerを起動する

## リファレンス
- [Microsoft, Linux ディストリビューションを構成する](https://docs.microsoft.com/ja-jp/windows/wsl/wsl-config)
- [Windows Subsystem for Linux 2(WSL 2)をセットアップしてみた](https://dev.classmethod.jp/articles/how-to-setup-wsl2/)
- [コマンドプロンプトで新規ファイルを作成する](https://mebee.info/2020/12/15/post-25819/)
【Vue.js】算出プロパティと監視プロパティの比較

#はじめに
こんにちは！
今回は【Vue.js】算出プロパティと監視プロパティについて比較していきます！

#算出プロパティ VS 監視プロパティ
算出プロパティと監視プロパティどちらでも実装できてしまう場合、基本的には**算出プロパティ**を利用することを推奨されている。理由としてはシンプルに記述することができるからである。


#書き方・解説
今回は以下のように、**firstNameテキスト**、**lastNameテキスト**を入力したら
`fullName: firstName スペース　lastName`
と表示されるようにしていきます。
これを`算出プロパティ`と`監視プロパティ`で記述し比較していきます。

![スクリーンショット 2021-10-19 20.51.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/0bc4ddd4-2adf-a495-4374-d9fbf1a0cd96.png)


```HTML:HTML
<div id="app">
  <p>
    firstName: <input type="text" v-model:value="firstName">
  </p>
  <p>
    lastName: <input type="text" v-model:value="lastName">
  </p>
  <p>
    fullName: {{ fullName }}
  </p>
</div>
```
HTMLはどちらも変わらず。
##⏬算出プロパティ

```Vue.js
var app = new Vue({
  el: "#app",
  data: {
    firstName: '',
    lastName: ''
  },
  computed: {
    fullName: function() {
    return this.firstName + ' ' + this.lastName
    }
  }
})
```
##⏬監視プロパティ

```Vue.js
 var app = new Vue({
  el: "#app",
  data: {
    firstName: '',
    lastName: '',
    fullName: ''
  },
  watch: {
    firstName: function(value) {
      this.fullName = value + ' ' + this.lastName
    },
    lastName: function(value) {
      this.fullName = this.firstName + ' ' + value
    }
  }
})  
```
このようにどちらでも処理を実行できる場合、算出プロパティの方がコード量が少なくスッキリと記述できます。

#まとめ
どちらでも記述できる場合、算出プロパティで実行しましょう。

#最後に
今回は算出プロパティと監視プロパティの比較についてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
Ubuntuでdocker daemonのプロキシを設定する方法

# プロキシ環境下にてdocker pull

/etc/systemd/system/docker.service.d/override.conf

```
[Service]
Environment = 'http_proxy=http://example.com:xxxx' 'https_proxy=https://example.com:xxxx'
```
のように書く
arrow関数で名前付きの即時関数の書き方

やりたいこと

```.js
var result = (function (param1, param2) {
  return param1 + param2;
}(1, 2));
```

みたいな感じで、名前付きで即時関数をarrowで書きたかった

方法

```.js
const result = ((param1, param2) => {
  return param1 + param2;
})(1,2);
```

これでいけました。
Spring Boot 2.5以降でHTTP/2を試す

以前はHTTP/2試すのに色々と設定が必要だったが、https://hirakida29.hatenablog.com/entry/2019/11/30/231927 で書かれているようにSpring Boot 2.5以降はプロパティを一つ設定するだけになった。これを試す。

# ソースコード
```gradle:build.gradle
plugins {
  id 'org.springframework.boot' version '2.5.6'
  id 'io.spring.dependency-management' version '1.0.11.RELEASE'
  id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
  testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
  useJUnitPlatform()
}

```

以下のプロパティでHTTP/2が有効になる。

```properties:src/main/resources/application.properties
server.http2.enabled true
```

動作確認用に適当な```RestController```を作る。

```java
@RestController
@SpringBootApplication
public class App {
    @GetMapping("/hoge")
    public String hoge() {
        return "hoge";
    }
    
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

```

動作確認用の適当なclientを作る。

```java
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;

public class ClientSample {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
//        HttpClient client = HttpClient.newBuilder().version(Version.HTTP_2).build();

        HttpRequest request = HttpRequest.newBuilder(new URI("http://localhost:8080/hoge")).build();
        HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
        
        System.out.println(response.version());
    }
}

```

これを実行すると```HTTP_2```と表示される。

<code>HttpClient.newHttpClient()</code>のようにversion未指定だとデフォルトは```Version.HTTP_2```なので、特にversion指定の必要はない。
Team Geek を読んだまとめ

# Team Geekまとめ

## チームで働くときの三本柱はHRT
- 謙虚(Humility)
- 尊敬(Respect)
- 信頼(Trust)

恥ずかしいからと言って自分が行っているタスクの進捗を隠すことは、より良いプロダクトの開発において得策ではない。

チームの文化とは、エンジニアリングチームが共有する経験・価値・目標のことである。

ミーティングは効率的に行うべきである。前もってアジェンダを共有しておき、直接話さなくてはいけない内容のみ会話することで、効率的なミーティングを行うことができる。

## チームにリーダーは必要である
チームリーダーは技術的なリーダーと精神的なリーダーの二つがある。精神的なリーダーは部下たちの人間的な問題にも考慮し、より良いチームを作っていくのに必要である。

チームとしての目標を明確にすることで、効率が劇的に向上する。全員が同じ目標に向かっていればお互いのフィードバックなどによりさらに良いものを作ることができる。

## 人は植物のようなものである
人にはそれぞれ成長に必要なものが違う場合の方がほとんどである。
全員に同じものを与えてもそれが平等であるとは限らない。日光で育つ植物もあれば、肥料や水を厳密に管理して育つ植物もあるように、人間も人それぞれ成長因子が違う。

そのため、誰かに教えるときはその人が何を必要としているのか常に考え続けるべきで、そうすることで彼らのモチベーションを上げることもできる。

## 有害なものへの対処
他人の時間を尊重し、高度なコミュニケーションをとることを意識する。感情的にならず、長期的思考を持って最善の行動を心がける。

## ユーザーも人間である
使いやすいソフトウェアは成功するソフトウェアになりうる。Googleではレイテンシーの向上を事前告知なしに行った結果、利用のアクティビティグラフが増加していた。速度は機能である。
また、いろいろな機能を追加してクールな物を作ることは、ユーザー視点では良いソフトウェアとは言えないことが多い。機能が多すぎて圧倒してしまうのではなく、より少ない機能であることの方が良い。

複雑さを巧妙に隠すことによって、ユーザー側に不自由にしないことがユーザビリティの目指すところである。

技術的にエンジニアの方がユーザーよりも上であることを傲慢に思ってユーザーを見下したりしてはいけない。開発には常にHRTの精神で行うべきである。

ユーザーのことを忘れない３つのこと
- マーケティング
- ユーザビリティ
- 顧客サービス

**一番大事なのはHRT！！！**
GPU-enabled TensorFlow 2.6 via PIP in conda env without system-wide CUDA/cuDNN installation on Windows PC

# 手順
  1. Miniconda 最新版をダウンロード・インストール
  1. 適当に `conda create -n hogehoge`
  1. `conda activate hogehoge`
  1. `conda install cudnn cudatoolkit` <--- CUDA関係は conda に任せる．
  1. __`pip install tensorflow`__ <--- __PIP でインストール__する．__conda は使わない__

# 解説

> `conda install cudnn cudatoolkit` <--- CUDA関係は conda に任せる．

CUDAやcuDNNやらをバージョン不整合に注意しながら，個別にダウンロードして管理者権限でシステム全体にインストールして……とがんばるやり方がよく見かけるやり方です．
が，実は__CUDA等はcondaに任せてシステムインストールしない__という選択肢があります．
これが個人的にお手軽でした．システム環境全体を汚さずにも済む．

> `conda install ipython`

ここは python をインストールために適当なパッケージ指定している．
利用予定のバージョンの tensorflow に適合する Python が入れば numpy 以外なら何でもよい（Numpyを先にインストールして後からtensorflowを入れると不整合が生じた経験があるので，TensorFlowのインストール時に任せる）．

> __`pip install tensorflow`__ <--- __PIP でインストール__する．__conda は使わない__

ここがポイントです．
残念ながら，`conda install tensorflow` で GPU 計算可能な tensorflow のインストールは 2021年11月現在はうまくいきませんでした．
しかし，PIP では GPU が有効な版をすんなりインストールすることができます．
仮想環境のJupyter上で異なる仮想環境のカーネルを使う

## 概要
* Jupyter labを立ててる仮想環境上で、違う仮想環境のカーネルを使う

作業環境

>* python3.8
>* venv
>* Windows PowerShell(基本的なコマンドは環境で変わりません)

## はじめに
カーネルを追加する際に、ちょっと戸惑ったので備忘録として残しておきます。
どのサイトも割と`pip`で`ipykernel`を追加する記載しかなかったので、初めての人向けに紹介したいと思います。

参考サイト
>* [Jupyter Notebookでカーネルを増やそう](https://qiita.com/SaitoTsutomu/items/a3d27a2de1ff3e762771)

## メイン
まずは、新たにカーネルを追加した仮想環境上で`jupyter`をインストールします。
`jupyter`をインストールすると`ipykernel`も入ってるので、個別にインストールする必要がなくなります。
また`ipykernel`だけインストールしても、もちろんエラーを吐くので、個人的には`jupyter`のインストールだけのほうが楽ですね。

```.shell
pip install jupyter
```

インストール後にjupyterをインストールした仮想環境上で、以下のコマンドを実行し新しくカーネルを追加します。
`--name`のところはカーネルの名前です。

```.shell
python -m ipykernel install --user --name test
```

以下の実行結果がでたらカーネルの追加は成功です。

```.shell
Installed kernelspec test in C:\ProgramData\jupyter\kernels\test
```

`jupyter-lab`の右上のカーネルを選択し、

![Untitled.ipynb (5) - JupyterLab - Google Chrome 2021_10_28 19_45_45_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/199a4f4b-9d10-1f95-4169-9a78e4bf5639.jpeg)


testのカーネルに変更することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/a95b9ad0-c8b2-6162-cf26-49ca5331df6c.png)

ライブラリの追加なども、notebook上で行うことは出来ますが、ターミナルでインストールするほうがいいのかなと思います。
notebook上では、`!pip install pandas`のコマンドだけだと、jupyterを立ててる仮想環境上のpythonにインストールされてしまうので、注意が必要です。
[AndroidStudio]Androidエミュレータのシステムイメージを削除する

#概要
Androidエミュレータのシステムイメージ(Android10とかAndroid11とか)は、数GB単位でハードディスクを圧迫しています。今後使う予定のないシステムイメージは削除しておくと幸せになれるかもしれません:four_leaf_clover:
![スクリーンショット 2021-10-28 16.46.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/29dc3145-4ef2-cd35-0189-d502d595fce2.png)

#本文
【 Windows 】
(ユーザーフォルダ)/AppData/Local/Android/Sdk/system-images/
(AppDataは隠しフォルダです)
【 mac 】
~(ホームのフォルダ)/ライブラリ/Android/sdk/system-images/
(ライブラリは隠しフォルダです)

system-imagesフォルダの中の使う予定が無いシステムイメージをフォルダごと消します。
#補足
普段常用してるシステムイメージを間違って消さないように、確認してから消去してください:confounded:
ArduinoでNeoPixelを動かす

# NeoPixelとは
フルカラーのLEDです。連結して使用することができます。


# 配線
NeoPixelの+5V(赤）ーーー>Arduinoの5V
NeoPixelのDin（黄）ーーー>Arduinoの9番ピン(470Ω程度の抵抗を入れる)
NeoPixelのGND（黒）ーーー>ArduinoのGND
とつなぎます。

Arduinoから電源を取ろうとすると連結は5個が限界だと思います。
それ以上にすると、Arduinoが壊れるので、沢山連結する場合は
+5V、GNDは外部電源とつなぎましょう。


# ライブラリのインストール
[ここ](https://youtu.be/oTgIimvlkis)を参考にAdafruit_Neopixelライブラリをインストールしてください。


# プログラム

```java
#include <Adafruit_NeoPixel.h>
#define PIN        9 // 信号用のピンを指定
#define NUMPIXELS 5 // LEDの数を指定
int brightness=50;//明るさ

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pixels.begin(); // NeoPixel出力ピンの初期化
  pixels.setBrightness(brightness);
}

void loop() {
  pixels.clear(); // すべてのLEDの色を0にセット

  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(100, 255, 100));
    pixels.show();
    delay(1000);
  }
}
```

## ポイントの文法（For文）
下記のようにすると処理が3回繰り返されます。0,1,2
i++はiがループするたびに１ずつ足される。
iが0から始まり、3未満の時はfor文の中の処理を繰り返す。
長縄跳びをイメージしましょう。回数を数えながら繰り返し、やめると決めた回数で終わるようなイメージです。

```java
   for (int i=0; i < 3; i++){
      処理;
   }
```
【業務効率化】フォルダ内のファイルを自動的に合体させる方法~非エンジニアメモ

# モジュールのインポート
```
import glob
import os
```

# 空のDataFrameを定義
```
df = pd.DataFrame(columns= [])
```
# .csvを含むファイル全てをpd.read_csv()で読み込む
```
for i in glob.glob("*.csv"):
    tmp_df = pd.read_csv(i,encoding="cp932",low_memory=False)
    df = pd.concat([df,tmp_df]) # DataFrameを連結する
```
クラウド化された現代においても物理サーバーの知識は必要か

## 結論　必要

クラウド化された現代においても物理サーバーの知識は必要か
答えは必要だと信じている

特にクラウドだと、OSI参照モデルやTCP/IPの理解に時間がかかると思う。

L2スイッチやMACアドレスなどなど、インフラはとにかく用語が多い上に、似たような単語も多い
てかMACアドレスとかIPアドレスとかリンクローカルアドレスとか、アドレスだけでどれだけ出てくるねんっていうレベル

で、物理サーバーでどうなっているっていうのがわかれば、この辺りが視覚でも理解できるのが大きい

逆にクラウドだと一生理解できないまま、とりあえず暗記しかできない

困るケースとしてはその場合はほぼハンズオンでしか仕事ができないということ
つまり要件定義や設計の仕事は難しいのではなかろうか
Amazon EBS-BackedとInstance Store-Backedの違い

##Amazon EBS-Backedとは？
Amazon EBS-Backedとは、OSがインストールされるルートボリュームがEBS上のこと。

`特徴`

| インスタンスの起動時間 | 通常1分以内 | 
|:-----------|:------------|
| インスタンスの起動時間| 通常1分以内        | 
| ルートデバイスのサイズ制限|16TiB | 
| ルートデバイスボリューム|AmazonEBSボリューム| 
| データの永続性| デフォルトでは、インスタンスを終了するとルートボリュームは削除される。AmazonEBSにある他のデータは全て、インスタンスの終了後もデフォルトで保持される|
| 変更| 料金はインスタンス使用料、Amazon EBSボリューム、Amazon EBSスナップショットとして保存したAMIに対して発生する|
| 料金|料金はインスタンス使用料、Amazon EBSボリューム、Amazon EBSスナップショットとして保存したAMIに対して発生する|
|停止状態|停止状態にすることは可能。ただしルートボリュームはEBSに保持される|


##Amazon Instance Store-Backedとは？
Instance Store-Backedとは、OSがインストールされるルートボリュームがインスタンスストア上のこと。

`特徴`

| インスタンスの起動時間 | 通常1分以内 | 
|:-----------|:------------|
| インスタンスの起動時間| 通常5分以内| 
| ルートデバイスのサイズ制限|10GiB| 
| ルートデバイスボリューム|インスタンスストアボリューム| 
| データの永続性| インスタンスストアボリューム上のデータは、インスタンスの存続中のみ使用可能|
| 変更| インスタンスの属性はインスタンが削除されるまで固定|
| 料金|インスタンスの使用料やS3に保存したAMIに対して発生する|
|停止状態|インスタンス実行中も終了後も、停止状態にすることはできない|
【RSpecエラー】validate_uniqueness_ofを使うとテストが通らないとき

##環境
Ruby 3.0.2
Rails 6.1.4.1



##状況

バリデーションのテスト実行時に下記のエラー
デフォルトでは大文字と小文字を区別している

```model.rb
validates :email, uniqueness: true
```

```spec.rb
it { is_expected.to validate_uniqueness_of(:email) }
```

```
Expected Employee to validate that :email is case-sensitively unique,
       but this could not be proved.
         After taking the given Employee, setting its :email to ‹"dummy
         value"›, and saving it as the existing record, then making a new
         Employee and setting its :email to a different value, ‹"DUMMY VALUE"›,
         the matcher expected the new Employee to be valid, but it was invalid
         instead, producing these validation errors:
```

##解決法

大文字小文字の区別なくテストする```ignoring_case_sensitivity```メソッドを追加

```spec.rb
it { is_expected.to validate_uniqueness_of(:email).ignoring_case_sensitivity }
```

##参考

https://github.com/thoughtbot/shoulda-matchers/issues/1116
DatabricksのPhoton

[Photon \| Databricks on AWS](https://docs.databricks.com/runtime/photon.html) [2022/7/27時点]の翻訳です。

Photonは、Databricksにおけるネイティブのベクトル化されたクエリーエンジンであり、既存のコードを実行できるようにApache Spark APIと直接互換性があります。モダンなハードウェアを活用できるようにC++で実装されており、CPUにおけるデータ、命令レベルの並列性を利用するために、ベクトル化クエリー処理における最新技術を活用しています。さらには、データレイクに対してネイティブに動作することで、実世界のデータとアプリケーションにおけるパフォーマンスを改善しています。Photonはお使いのSQL、データフレームAPIを高速に実行する高性能ランタイムの一部であり、ワークロードあたりのトータルコストを削減します。Databricks SQLウェアハウスではデフォルトでPhotonが使用されます。

# Databricksクラスター

DatabricksクラスターでPhotonにアクセスするには、[UI](https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#databricks%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0)あるいはAPI([Clusters API 2\.0](https://docs.databricks.com/dev-tools/api/latest/clusters.html)、[Jobs API 2\.1](https://docs.databricks.com/dev-tools/api/latest/jobs.html)において、`<databricks-runtime-version>-photon-scala2.12`の文法に従い`spark_version`を指定します)を用いてクラスターを作成する際に明示的に[Photonを含むランタイムを選択](https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#databricks%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0)する必要があります。Photonは、[Databricksランタイム 9.1 LTS](https://docs.databricks.com/release-notes/runtime/9.1.html)以降で利用できます。

Photonは、サポートするドライバーノード、ワーカーノードのインスタンスタイプを限定しています。Photonインスタンスタイプは、非Photonランタイムを実行する同じインスタンスタイプとは異なるレートのDBUを消費します。PhotonインスタンスとDBU消費に関しては、[Databricksプライシングページ](https://databricks.com/product/aws-pricing/instance-types)をご覧ください。

# Photonのカバレッジ

**オペレーター**

- Scan, Filter, Project
- Hash Aggregate/Join/Shuffle
- Nested-Loop Join
- Null-Aware Anti Join
- Union, Expand, ScalarSubquery
- Delta/Parquet Write Sink
- Sort
- Window Function

**エクスプレッション**

- Comparison / Logic
- Arithmetic / Math (ほぼすべて)
- Conditional (IF, CASEなど)
- String (一般的なもの)
- Casts
- Aggregates(一般的なものの大部分)
- Date/Timestamp

**データタイプ**

- Byte/Short/Int/Long
- Boolean
- String/Binary
- Decimal
- Float/Double
- Date/Timestamp
- Struct
- Array
- Map

# 利点

- DeltaおよびParquetテーブルに対するSQLおよび同等のデータフレームオペレーションをサポート。
- 大量のデータ(100GB以上)に対する集計、ジョインを含むクエリー処理の高速化が期待できる。
- Deltaキャッシュから繰り返しデータがアクセされるときの高速なパフォーマンス。
- 多くのカラム、多くの小規模ファイルを持つテーブルに対するスキャン性能の安定化。
- 特に幅の広いテーブル(数百から数千のカラム数)において、`UPDATE`、`DELETE`、`MERGE INTO`、`INSERT`、`CREATE TABLE AS SELECT`を用いたDelta、Parquetへの書き込みの高速化。
- ソートマージジョインをハッシュジョインで置き換える。

# 制限

- Spark構造化ストリーミングは未サポート。
- UDFは未サポート。
- RDD APIは未サポート
- 短時間のクエリー(2秒未満)、例えば、小規模データに対するクエリーでは性能改善が期待できない。

Photonでサポートされていない機能は、Databricksランタイムと同じように実行されます。これらの機能における性能面での利点はありません。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
[python/boto3] Amazon Athenaの同時実行数制御のため、実行中件数を取得してみた


Amazon Athenaは素晴らしいサービスです。
もうSQLはAthena以外では書きたくない。。。

だって、index貼らなくていいし、重い重い処理かけてもDBサーバーごと落ちたりしない（注意：タイムアウトはあります。）から、効率考えずに書きたいクエリをかける！
MySQLだと、2000万件とかセレクトしに行ったらどうしよう、とか。
スロークエリになって他の処理に影響与えてしまわないかな、とか。心配事が尽きないです。。。

その点、Athenaはインフラのリソース気にしなくてクエリ投げ放題なんて、<b>天国のSQL</b>です！！
だから、ぜひ、使い倒したいところです。


ただ、同時実行数がデフォルトだと、たった20しかありません！（BigQueryは100なのに！上限解除もできるみたいですが）
だから、実行しようとした時に、20以上動いていたら、StepFunctionsとかでWait処理かけたいですよね？

その時に使える、boto3で実行中のクエリ数（State = Queued , Running)を取得するコードを書きました。Queuedも一応入れときました。
20件のStateを取れればいいんですが、一応、何件でも遡って取得できるようにしています。（上限解除している人のためにも）

```Python
import boto3

# Athenaの実行中の件数を取得する関数
def count_athena_workings(works:int=30):
    client = boto3.client('athena')
    ret = []
    def get_list(works,ret,next_token=''):
        max_num = 50 #2021年10月現在、list_query_executionsの上限が50
        work_nums =  max_num if works > max_num else works
        works -= max_num # 実行した分を減算
        
        if next_token: #2ページ目以降を取得する場合
            res = client.list_query_executions(NextToken=next_token,MaxResults=work_nums,WorkGroup='primary')
        else: #1ページ目を取得する場合
            res = client.list_query_executions(MaxResults=work_nums,WorkGroup='primary')
        next_token = res['NextToken'] #次のページ実行するためのnext_tokenを取得

        res2 = ''
        if res['QueryExecutionIds']:
            res2 = client.batch_get_query_execution(QueryExecutionIds=res['QueryExecutionIds'])
        
        for q in res2['QueryExecutions']:
            if q['Status']['State'] in ['QUEUED','RUNNING']:  # 'State': 'QUEUED'|'RUNNING'|'SUCCEEDED'|'FAILED'|'CANCELLED'
                ret.append(q['QueryExecutionId'])
                
        if works > 0: #2ページ目以降は再起的に取得
            ret = get_list(works,ret,next_token)
            
        return ret
            
    ret = get_list(works,ret) #初期実行
    
    return len(ret)
```

これで、Athenaを存分に働かせられますね！
（もっと良い方法があれば教えてください！）

Athenaを思い通りに操れると、データ分析し放題です！
億単位のレコードでも、大丈夫！
何百万レコードとか、ちょっと少ないくらいに感じる、この優越感が最高です。
VS Codeの拡張機能：Live Sass Compilerではuseとforwardが使えない

※この記事は2021年10月28日に書いた記事になります。

#Live Sass Compilerについて
**Live Sass Compiler**はVS Codeの拡張機能であり、これをインストールすると自動でSassからcssへと変更する非常に便利なものです。しかし、少し対応していないことがあります。それがUseとforwardが使えない点です。

#Sass公式はimportを推奨していない
[公式](https://sass-lang.com/documentation/at-rules/import)には以下のことが書いてあります。

"**The Sass team discourages the continued use of the @import rule.** Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the @use rule instead. (Note that only Dart Sass currently supports @use. Users of other implementations must use the @import rule instead.)"

つまり、推奨してないんですね。この原因としては別々のファイルに同じ変数やmixin、変数などを用いた場合には対立が起こるかららしいです。

そして、それを解決するために作られたものがuseとforwardです。

#Live Sass Compilerではimportしか使えない！？
私は初心者なのでそのことを知らずに使おうとしたのですが、全く反応しませんでした。これはuseとforwardをサポートしているコンパイラが今のところDart Sassしか無いみたいことが原因だそうです。つまりLive Sass CompilerはDart Sassをコンパイラとして使っていないので、importを使うしかないということです。

#結論
Live Sass Compilerを使うときはimportを用いましょう。
どうしてもDart Sassを使いたい場合は同じVS Codeの拡張機能である「DartJS Sass Compiler」と「Sass Watcher」を使うと出来るようです。気になる方は「dart sass vscode」と検索して調べてみてください！
DockerのコンテナのVolumeを確認する

以下Docker for Macが前提です。

まず該当のVolumeを突き止めるためにVolumeの一覧を取得

```
% docker volume ls
-> 
Driver  Volume name
local   foo
local   bar
...
```

次に該当のVolumeのmountpointを取得

```
% docker volume inspect foo
-> 
{
  "Created_at": ...,
  "Driver": "local",
  "Labels": ...,
  "Mountpoint": "/var/lib/docker/volumes/foo/_data",
  "Options": null,
  "Scope": "local"
}
```

docker for MacではVolumesのmountpointのディレクトリにホストOSのターミナルから入ることができないので、
Docker EngineのVMにnsenterを使ってSSHを使わずにコンテナに入る。

***** memo *****
nsenter -> ENTER Name Space
dockerが作ったNameSpaceに入るコマンド
***** memo *****

以下のコマンドでVM内に入れる。

```
% docker run -it --rm --privileged --pid=host justincormack/nsenter1
```
[参考](https://gist.github.com/BretFisher/5e1a0c7bcca4c735e716abf62afad389)

目的のvolumeに移動。

```
% cd /var/lib/docker/volumes/foo/_data
PySide2(Qt for Python)はPython3.10では動かない

# 困った内容
PySide2を使いたいけどPython3.10環境で

```
pip install PySide2 
```

ってインストールしようとしても以下のエラーが出てしまう人へ

```
ERROR: Could not find a version that satisfies the requirement pyside2 (from versions: none)
ERROR: No matching distribution found for pyside2
```

# 解決法

https://wiki.qt.io/Qt_for_Python

これを見ると今の所Python3.5からPython3.9まででしか動かないとわかります。
## Python3.9.7をインストールする

https://www.python.org/downloads/release/python-397/

ここにアクセスしてから下までスクロールして、インストーラー等をダウンロードします。
必要ならPATHとかも設定してもらって
## 動くようになる
以下を実行します。

```
pip install PySide2
```

多分無事にインストールできるはずです。

# 参考文献

https://stackoverflow.com/questions/58743664/why-do-i-keep-getting-errors-when-i-try-to-install-pyside2-on-windows-pc

https://wiki.qt.io/Qt_for_Python
初歩的なgitコマンド

###初期設定
以下を設定することでコミットを行った際に、誰が行ったコミットか分かるようになる。

```
$ git config --global user.name "ユーザー名"
$ git config --global user.email "メールアドレス"
```

###変更内容確認
```
$ git status
```

###差分
```
$ git diff <ファイル名>
```

###ファイルの追加
```
$ git add <ファイル名>
```

###追加したファイルをコミット
```
$ git commit -m "変更内容"
```

###プッシュ
```
$ git push origin <ブランチ名>
```
UniRxタップ判定

# はじめに

画面上自由なところをタップして次のページを表示するといったことがあると思います。
タップした時、指をすぐに画面から離さないと判定されない処理をUniRxで書きます。

# タップ判定処理

UniRxを使用して簡単に書くと以下のようになります。

```csharp
Observable.EveryUpdate()
 .Where(_ => Input.GetKeyUp(0))
 .Subscribe(_ => { Debug.Log("Tap!"); })
 .AddTo(this);
```

こちらでもタップとして判定されますが、画面にずっと指を置いた後に離しても判定されてしまいます。

私が思うタップは指をすぐに話したときに判定されるもので、画面から指が離れた時をタップと呼ぶのは少し違うと感じています。
そこで以下のように書きました。

```csharp
var mouseDown = Observable
.EveryUpdate()
.Where(_ => Input.GetMouseButtonDown(0))
.Select(_ => Time.realtimeSinceStartup);

var mouseUp = Observable
.EveryUpdate()
.Where(_ => Input.GetMouseButtonUp(0))
.Select(_ => Time.realtimeSinceStartup);

mouseDown.Merge(mouseUp)
    .Buffer(2)
    .Where(ls => ls[1] - ls[0] < 0.2f)
    .Subscribe(_ => {
        Debug.Log("Tap!");
    }).AddTo(this);

```

こちらで、0.2秒以内に指を離さないと判定されなくなります。
順番に処理を解説していきます。

## MouseDown, MouseUp

```csharp
var mouseDown = Observable
.EveryUpdate()
.Where(_ => Input.GetMouseButtonDown(0))
.Select(_ => Time.realtimeSinceStartup);

var mouseUp = Observable
.EveryUpdate()
.Where(_ => Input.GetMouseButtonUp(0))
.Select(_ => Time.realtimeSinceStartup);
```

それぞれEveryUpdateで毎フレームマウスが押されたまたは離された時に、その時の経過時間を流すようにしています。

## Merge

```csharp
mouseDown.Merge(mouseUp)
```

こちらでマウスダウンとアップを合成して、いずれかの状態を満たした時に経過時間が流れるようにしています。

合成する関数は他にConcatとZipがありますが、今回の場合はMergeが適しています。
[合成方法参考](https://light11.hatenadiary.com/entry/2018/11/20/225152)

## Bufferで経過時間を比較する

```csharp
    .Buffer(2)
    .Where(ls => ls[1] - ls[0] < 0.2f)
```

Bufferは流れてきたデータを指定数まとめてからリストにして流す処理です。
[Bufferについての参考](https://qiita.com/toRisouP/items/f5cb995d811e6bcef293)

経過時間がリストで２つ渡されてくるので、こちらの２つの差を満たしていたらSubscribeの処理が呼ばれるようになります。

今回の場合はDown→Upの順番で流れるので、順番は保証されています。
例えば、左クリックと右クリックの順で短い間隔で行われたかどうかを判定したい場合は、
経過時間とマウスボタンIDをまとめて送って順番を見る必要があるかと思います。

# 最後に

普段複雑な合成などをしないので、スムーズに書けるように腕を上げたいですね
RailsからGoogleスプレッドシート連携させる際に認証でつまづいた点(2021/10時点)

# はじめに
よくあるRailsアプリケーションからGoogleスプレッドシートに連携するのを実装したかったのだが盛大につまづいたのでポイントをメモ
大まかな手順としては以下などを参考にしてください
https://japan.appeon.com/technical/techblog/technicalblog019/
https://techblog.hacomono.jp/entry/2020/10/21/095900

## OAuth 同意画面のアプリケーションの種類で「その他」が選択肢にない
![スクリーンショット 2021-10-28 18.08.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/2dfbedf8-6225-5466-ea10-c9451d341a0c.png)

「その他」がないなら「ウェブアプリケーション」だろうなぁと思ってたら落とし穴。
承認エラーになります
![スクリーンショット 2021-10-28 18.03.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/613ea752-f3b4-2b2c-43e9-7089bf63b64e.png)

自分の場合は「デスクトップアプリ」を選択したら承認されるようになりました。

## 初回認証時に、コンソールに表示される1. Open this page: にアクセスした後、コンソールに　2. Enter the authorization code shown in the page:　が表示されない

Railsアプリケーション内で初回認証をしようとしていて発生。
こちらを参考にしました
https://japan.appeon.com/technical/techblog/technicalblog019/

別ディレクトリに以下を置いて

Gemfile

```
source 'https://rubygems.org'

gem 'google_drive'
```

```main.rb
require "google_drive"

session = GoogleDrive::Session.from_config("config.json")

# 事前に書き込みたいスプレッドシートを作成しておく
sheets = session.spreadsheet_by_key("xxxxxxxx").worksheets[0]

# スプレッドシートへの書き込み
sheets[1,1] = "hello world!!"

# シートの保存
sheets.save
```

```config.json
{
  "client_id": "xxxxxxxx.apps.googleusercontent.com",
  "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
```

下記コマンドを実行

``````
$ bundle install
$ bundle exec ruby main.rb
```

コンソールに以下が表示され、認証コードがペーストできるように

```
2. Enter the authorization code shown in the page:　
```
git push heroku masterをしたら、Precompiling assets failedが表示された時の対処法

**結論**
-
webpackerをインストールしていませんでした。

**エラー文**
-

```ruby:ターミナル

remote:  !     Precompiling assets failed.

#省略

error: failed to push some refs to ~~~
```

**解決までの流れ**
-

赤字で書かれていた上の2つの文をそれぞれGoogleで調べましたが、自分にあった対処法が見つけられませんでした。
色々と悩みましたが、ログを上から順に見ていくことにしました。
そうすると、大事なことが書かれている部分を発見しました！

```ruby:ターミナル
#省略
remote:        webpack binstubs not found.
remote:        Have you run rails webpacker:install ?
```

「webpackないよ？　rails webpacker:installした？」　と言われていました。

なので、

```ruby:ターミナル
rails webpacker:install
```

無事にインストールされ、再び　git push heroku master　を実行しました。
今度こそ、成功しました。

**最後に**
-
エラーが出ると、どうしても赤字になっているところに注目してしまいますが、前後にも目を向けて対処していきたいです。
Windowsサービスとして登録しているTomcatの使用メモリを変更する

#概要

Tomcatを使ったWebアプリケーション（Windowsサービスとして登録）で下記のエラーが出ていたため、メモリを増やしてみた。
試行錯誤した過程とともにその方法を書く。
java.lang.OutOfMemoryError: PermGen space

* 環境・バージョン
  + Windows 10 Pro
  + Java7
  + Tomcat6


#試行錯誤の過程

1. setenv.batに設定を書いてみる（→サービスの場合うまくいかない）
1. tomcat6w.exeをダブルクリックしてみる（→サービスの名前を変更している場合うまくいかない）
1. うまくいった方法１（コマンドで・・・）
1. うまくいった方法２（レジストリを・・・）

## 1．setenv.batに設定を書いてみる（→サービスの場合うまくいかない）

Tomcatを使ったWebアプリケーション（Windowsサービスとして登録）で下記のエラーが出ていた。
> java.lang.OutOfMemoryError: PermGen space

Tomcatのメモリの設定の仕方を検索すると、
JavaVMの起動オプションでCATALINA_OPTSを設定するとか、
CATALINA_OPTSの設定をcatalina.batまたはsetenv.bat（catalina.batから呼ばれる）に書くとか出てくる。

Tomcatのフォルダ\bin\setenv.batを作成し、

```conf:bin\setenv.bat
set CATALINA_OPTS=-Dfile.encoding=UTF-8 -Xms3072m -Xmx3072m -XX:PermSize=256m -XX:MaxPermSize=256m -server
```

と書いてみるが、うまく反映されているように見えない。
どうやらWindowsサービスにしている場合はsetenv.batに書いても反映されないらしい。

## 2．tomcat6w.exeをダブルクリックしてみる（→サービスの名前を変更している場合うまくいかない）

Windowsサービスにしている場合、Tomcatのフォルダのbin\tomcat6w.exeを起動すると設定画面が開くという情報があり、
ダブルクリックしてみるが・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568592/b8168d67-e7a9-dbfe-2d05-b3a92a3354d2.png)
「指定されたサービスはインストールされたサービスとして存在しません。」
というエラーメッセージが表示される。
どうやらサービスの名前を「tomcat6」から変えているので開かないらしい。
また、設定画面を開いて設定変更するのもよいが、複数のクライアントに配布しているアプリケーションのため、できればバッチファイルをクリックしただけでメモリサイズの変更がされるようにしたい・・・。

## 3．うまくいった方法１（コマンドで・・・）

結局公式サイトにたどりつき・・・希望通りコマンドで設定を変えることができるようになった！

Apache Tomcat 6.0　Windows service HOW-TO
https://tomcat.apache.org/tomcat-6.0-doc/windows-service-howto.html

設定画面を表示するときは **tomcat6w.exe //ES//[サービス名]**　←「tomcat6」の後にｗあり

```
(Tomcatのフォルダ)\bin\tomcat6w.exe //ES//[service-name]
```

設定を書き換えるときは **tomcat6.exe //US//[サービス名]**　←「tomcat6」の後にｗなし

```
(Tomcatのフォルダ)\bin\tomcat6.exe //US//[service-name] ++JvmOptions="-Xms1024m" ++JvmOptions="-Xmx3072m" ++JvmOptions="-XX:PermSize=256m" ++JvmOptions="-XX:MaxPermSize=512m" --JvmMs=1024 --JvmMx=1024
```

↑ パラメータ名の前に「--」を付けると上書き、「++」を付けると追加になる
（何度も実行すると、実行するたびに追加されていく・・・）

## 4．うまくいった方法２（レジストリを・・・）

Daemon - Daemon : Procrun
https://commons.apache.org/proper/commons-daemon/procrun.html

このサイトの一番下に書いてあるが、レジストリを直接編集するという方法もある。

32bitOS
> HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\ProcRun 2.0\<ServiceName>\Parameters

64bitOS
> HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\ProcRun 2.0\<ServiceName>


#参考URL

Apache Tomcat 6.0　Windows service HOW-TO
https://tomcat.apache.org/tomcat-6.0-doc/windows-service-howto.html

Daemon - Daemon : Procrun
https://commons.apache.org/proper/commons-daemon/procrun.html

起動時のプロパティとオプションの設定
https://ja.confluence.atlassian.com/adminjiraserver/setting-properties-and-options-on-startup-938847831.html
→ここに全部書いてあった！
【クラス内関数のselfがクラス変数として扱われない⁈なんで??】ってなった時に読むやつ

# 回答

単刀直入に言えば、__インスタンス化していない__のが原因です。

# 解説

例えば、こんな感じでutilっぽく複数の関数を一つのクラスにぶら下げる形でまとめているとします。
（ここで違和感を感じたあなたはもうこの記事を読む必要はないですね笑）

```py
class SomeClass:
    def say_hi():
        print('hi')

    def output_arg(var1):
        print(var1)
```

さて、ここで下記のコードを実行したらどんな出力になるでしょうか。

```py
SomeClass.say_hi()
```

答えは「 hi 」ですね。
ただ、このコードにかっこを加えたこのコードを実行したらどうなるでしょうか？

```py
SomeClass().say_hi()
```

答えは__エラー__となります。

この()がつくことによる違いの理由は__インスタンス化しているかどうか__にあります。

一番上のコードをお見せした時に感じてほしい違和感の正体にもつながってきますが、
クラスは本来__インスタンス化されてから処理が行われる__のが一般的です。

よく見るのだとこんな感じですよね。

```py
class Human:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print('Hi, I am ' + self.name)

Mike = Human('Mike')
Mike.greet()

>>> Hi, I am Mike
```

このコードのポイントとしては、__Mike__という変数に__Human__というクラスをインスタンス化してあてがった形となっている点が挙げられます。

そのため、Pythonを習っていると出てくるようにClass内の関数にはselfが入っていて、
Mike.greet()と書いた時には、引数を入れなくても、関数がエラーなく実行されます。

つまり、インスタンス化している時（`Human('Mike').greet()`）には、教科書通り、greet()にselfの分の第1引数を書かなくてもよくなりますが、
インスタンス化しないでクラス内の関数を実行しようとする場合（`Human.greet()`）には、selfの分引数が省略されるみたいなのも発生しないんです。

# まとめると

こんな感じになります


●【パターン1】
`SomeClass().some_func(arg)`
　→インスタンス化しているから、呼び出したクラス内の関数のselfはクラス変数を参照する

●【パターン2】
`SomeClass.some_func(arg1)`
　→インスタンス化していない（クラスの中の関数に直接アクセスしているだけ）から、呼び出したクラス内の関数のselfは第1引数としてarg1を参照する

# 余談
個人的にはライブラリ的な扱いとして、`SomeClass.some_func(arg1)`みたいな書き方ができるようにプロジェクト作ってもいいのでは？とも一瞬思いましたが、
考えてみれば根本的なPythonのお作法から外れてみっともない気もするので、しっかりインスタンス化した方が望ましいと感じています。

ご拝読ありがとうございます！

# 追記

`SomeClass.some_func(arg1)`をPython本来の書き方で実現したい場合は`@staticmethod`のデコレータが使えました！

[こちらで頂いたコメント](https://qiita.com/SDTakeuchi/items/32857bc4ac57897077a0#comment-75684221aee659afeb0c)にてお教えいただきました。
勉強になります、ありがとうございます...！
djangoでの動的urlの取り扱いについてまとめてみた

本日のお題
-
今回はdjangoアプリでの動的urlの取り扱いについてまとめます。

動的urlとは、その時々の状況によってurlの一部もしくは全体が変化するようなもののことです。

viewsにパラメータを渡すためにurlの一部にレコードのidを混ぜ込む場合などが代表例ですね。

今回は例として/myapp/delete/xx(xxにはレコードのidが入る）というurlを動的に作成し、そこにリクエストを送ることでそのレコードが削除されるようにしてみたいと思います。

目次
-

- urls.pyの編集
- views.pyの編集
- テンプレートの編集

urls.pyの編集
-
動的urlを使ってレコードを削除するために編集する必要があるのは、urls.py、views.py、テンプレートの三箇所です。

まずはurls.pyを編集し、delete/xxへのリクエストでレコード削除の関数が呼び出されるようにします。

```python:urls.py
urlpatterns = [
  path("delete/<int:pk>/", views.myapp_delelte, name="myapp_delete")
]
```
<int:pk>がパラメータを埋め込む部分になります。
<パラメータの型:パラメータ名>のように記述します。

パラメータ名に関してはなんでも良いのですが、このあとviewsで同じ名前を使うのでpk(primary key)やidのようにわかりやすいものが良いと思います。

次に、このパラメータを用いてレコードを削除していきます。

views.pyの編集
-
views.pyを以下のように編集します。

```python:views.py
def myapp_delete(request, pk):
  Post.objects.filter(id=pk).delete()
  return render(request, "myapp/index.html")
```
requestに加えて、先程指定したpkを引数としているところに注意してください。
他は特に問題ないかと思います。

最後に、このdelete/xxへのリンクをテンプレート上に作成します。

テンプレートの編集
-
テンプレート上では以下のように書くことで、動的なurlを作成することができます。

```html
<!-- aタグを用いる場合 -->
<a href="{% url 'myapp:myapp_delete' post.id %}">

<!-- formタグを用いる場合 -->
<form method="post" action="{% url 'myapp:myapp_delete' post.id %}">
{% csrf %}
<button type="submit">削除</button>
</form>
```
要はhref属性の値の中にパラメータも入れてしまえば良いということですね。

終わりに
-
以上で動的なurlの作成方法については終了です。

パラメータの型についてはint以外でも指定できるみたいですが、そちらについては機会があればまとめます。