OmniAICreator/Qiita-1.07M huggingface dataset:
カテゴリーデータの加工

# 目的
アンケートなどを集計する時に、良い(5)、まあ良い(4)、どちらでもない(3)、あまり良くない(4)、良くない(5)といった順序尺度を「良い」、「悪い」の2値に分けたい場面があります。pythonではどのようにデータを加工すれば良いのでしょうか。

# 使用するデータ
SIGNATEさんの練習問題として公開されている[「レンタル自転車の利用者予測」](https://signate.jp/competitions/114) のtrain dataを使います。日曜日を0、月曜日を1、曜日が進むについて1つずつ増えて、土曜日が6になるデータがあります。これを土日を0として、平日を1にしたい場合どういうコードを実行すれば良いのでしょうか。

# 曜日データ'weekday'の確認
まずはデータを読み込みます。データフレームを使いますので、pandasも読み込みます。

```python
import pandas as pd
df = pd.read_csv('ファイルのパスをコピペして下さい')
```
曜日の変数名は'weekday'です。'weekday'のデータ数と内訳を確認します。

```python
df_1 = df['weekday']
print(df_1.count())
print() #空行を作るため
print(df_1.value_counts().sort_index())
```
出力は次の通りです。
![grouping_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688182/2a869b33-b837-1347-674b-671ec547adab.png)

件数が8645件、0から6までの合計と一致しますね。これを土曜日(6)と日曜日(0)を0、月曜日(1)から金曜日(5)までを1の2値データに変換します。

# for文

```python
tmplist=[]
for i in df_1:
    if i in [0,6]:
        tmplist.append(0)
    elif i in list(range(1,6)):
        tmplist.append(1)
    else:
        next
print(pd.DataFrame(tmplist).value_counts())

# 新たに変数'weekday2'を作成して、tmplistの結果を代入する
df['weekday2']= tmplist
print(df['weekday2'].value_counts())

# train data (df)に'weekday2'が追加されているか確認する
df.head()
```

出力結果を見ると、土日と平日の数は同じですし、'weekday2'が新しく追加されています。
![grouping_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688182/c7009c86-bba4-6492-a93e-04c1ea1ee4ea.png)


# while文

新しい変数'weekday2'を作って0(ゼロ)を代入します。そしてwhile文で平日を1に書き換えるというアプローチです。

```python
df_weekday = df.copy()
df_weekday['weekday2'] = 0
i = 0
while i <= 8644: #8645件あるが、ゼロオリジンなので、8644
    if  df_weekday.iloc[i, 7] in [1,2,3,4,5]: #i行7列目としてweekday列を指定
        df_weekday.iloc[i, 15] = 1 #15列目としてweekday_平日を指定
    i += 1

df_weekday['weekday2'].value_counts()
```
value_countsの結果が土日が2495件、平日が6150件で正しく出力されています。

# isin
アプローチはwhile文と同じですが、よりシンプルなコードで実行できます。

```python
df_isin = df.copy()
df_isin['weekday2'] = 0 #新しい変数'weekday2'を作って、全て0(zero)を入れる

# 平日を1にしたいので、1にするコードを用意する
df_isin.loc[df['weekday'].isin(list(range(1,6))),'weekday2']=1
df_isin['weekday2'].value_counts()
```
value_countsの結果が土日が2495件、平日が6150件で正しく出力されています。

# まとめ
for文、while文、isinそれぞれ2値にわけることができました。コードのシンプルさという意味ではisinが便利でした。
・新しい変数を用意して、
・そこに一旦すべて0を入れ込んで、
・平日だけ1に変換する
というアプローチでした。
LibreCAD を Ubuntu22.04 にインストール


「LibreCAD install Ubuntu18.04」
https://qiita.com/nanbuwks/items/1c669aa58e3acaa17dba

では、Ubuntu18.04 のレポジトリでの LibreCAD は問題がありソースからビルドして LibreCAD Version 2.2.0-rc1 をインストールしました。

Ubuntu 22.04 ではどうでしょうか?

公式ページ
https://librecad.org/#download
によると、

> Check your distributions preferred package manager, if LibreCAD is available there. But the version may be a bit older.
> 
> For Debian/Ubuntu distributions, you can use our Launchpad PPAs  for stable or daily versions.


ディストリビューションのパッケージは古いだろうとありますね。


公式ページレポジトリ
https://github.com/LibreCAD/LibreCAD
で公式のバージョンを調べてみると、Patch Version 2.1.3 が Latest となっています。
2.1.3 は released this 23 Sep 2016 なのでちょっと古いですね。

RC 版も有り、そちらは  2.2.0 Release Candidate 4 Pre-release が最新で released this 08 Jun 2022 となっています。

さて、Ubuntuレポジトリのバージョンはいくつでしょう?


```

$ sudo apt install librecad
```

としてインストールし、起動。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c7a4b94a-2316-85b0-f193-7a778b487dd7.png)

見慣れた画面です。バージョンを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d1418c02-f4e1-1759-7f61-6c818b612f6c.png)

2.1.3 でした。今回はこれを使うことにします。
Load key "/Users/sasakiyuuya/.ssh/github": invalid format git@github.com: Permission denied (publickey).

WARNING: UNPROTECTED PRIVATE KEY FILE!

上記のエラーは無くなったが次なるエラーが発生。


```
Load key "/Users/sasakiyuuya/.ssh/github": invalid format
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

何やら形式が無効でアクセスが拒否されたのことでリモートリポジトリから読み取ることができない、

よくわからなくなったので、下記サイトから一回リセットしてやり直し

https://qiita.com/aki4000/items/4c81bc2747bbd5e96d85

鍵を生成して、Githubに貼り付ける。

それでも下記ようなエラー発生
```
no such identity: /Users/sasakiyuuya/.ssh/github: No such file or directory
```
下記のサイトの参考
https://qiita.com/takuyanin/items/c6a097028a837052c90c

④の~/.ssh/config
```
Host github
    HostName github.com
    IdentityFile ~/.ssh/github_id_rsa
    User git
```

上記のHostName github.comが抜けていたので、追加したらエラー解消した。

あー長かった。
Qiita新着記事の誤字をチェックするツールをつくりました

## この記事は

[Qiita新着記事の誤字をチェックするツール](https://qiita-typo-finder-t13801206.azurewebsites.net/)をつくりました

用途👇

- 自分で投稿した記事の誤字をチェックする
- 誰かが投稿した記事の誤字を直して差し上げる

![Animation1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/87b3637a-f43b-77b5-9580-536ee0cf5f09.gif)


この記事は、ツールの紹介＆自分のための備忘録です

### 経緯・余談

Azureの勉強をしています
今年に入って[AZ-900とAZ-104の資格をとった](https://zenn.dev/t13801206/scraps/591b5824f29687)ので、つづけてAZ-204をとりたい

[AZ-204試験の紹介ページ](https://docs.microsoft.com/ja-jp/certifications/exams/az-204)によると

> 本試験の受験者は、要件の定義と設計から、開発、デプロイ、保守に至るまで、開発のすべての段階に参加するクラウド開発者です。

とのことで、Azureを使ってデプロイとかログの監視とかが必要そうなので
実戦形式で学習しようと思った次第

## ツールの紹介

:::note warn
まず初めに、このアプリはAzureのApp Service無料枠にデプロイしているので、アクセス数によっては使えなくなるかもです
:::

[過去に](https://qiita.com/t13801206/items/8f251c0dba5f051c2398)、Power Automateをつかって誤字を自動で修正していくデスクトップツールをつくった
その資産（と呼べるほどのものではない）を使いまわせると思ったので
今回は**誤字をみつけて、編集リクエストへ誘導するようなアプリ**をつくった

本来は１クリックで編集リクエストを飛ばせるまでいけたらよかったけど
編集リクエストを飛ばすAPIは用意されていないので、**クリップボードに修正文をのせるまで自動**で
そこから先、**編集リクエストを送るところは人力**になる

### 具体的な手順

:::note warn
Qiitaにログインしているブラウザでアクセスしてください（編集リクエスト画面に飛ぶために）
:::

[サイトにアクセス](https://qiita-typo-finder-t13801206.azurewebsites.net/)すると、Blazor丸出しの画面と対面する

左のナビゲーションバーの`Typo`をクリックすると下記画面が表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/32c7620f-239b-e55a-5dd2-13ed693e121a.png)

具体的な手順はサイト自体に載せている通り👇

1. <b>修正後</b>と<b>元記事</b>を比較します
1. 修正後の文章が正しければ、`Copy!`を押します（クリップボードに修正後の全文がコピーされます）
1. <b>タイトル</b>のリンクをクリックすると、編集リクエスト画面が新しいタブで開きます
1. クリップボードの文章を貼り付けて、差分を確認し、編集リクエストを送信します

:::note info
リンク内の誤字や、文脈的に誤字ではないと判断した場合は、ゴミ箱ボタンを押してください。その行が非表示になります
:::

### 中身

1. サイトへのアクセスがあったらQiitaAPIを１回たたいて、新着の100件を取得する
1. jsonの応答の中から`body`をとってきて、誤字があるか判定する関数に入力する
1. 誤字があれば、`\n`で区切って誤字がある文だけを画面に表示する

#### 特筆すべきイマイチな点

画像と同じ行に誤字があると、テーブルが大きく崩れる

## 備忘録

### クリップボードにテキストを送るところはJavascriptの力を借りた

https://qiita.com/t_ngmn/items/9a322a5b806955c7e43f

### マークダウンをHTMLに変換するライブラリ

https://qiita.com/soi/items/a149eec9228bd6d54054

### App Serviceのタイムゾーンを東京にする

https://qiita.com/yossihard/items/67c80489457967c28db7

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/b9e2a655-75b9-486e-b81c-9441cb7ebd39.png)

### Application Insightの使い過ぎに注意する

ログを送りまくると

LogAnalytics(31日)もApplicationInsight(90日)も規定では無料範囲内の保存期間になっている

https://qiita.com/fukasawah/items/695141a2581c307af87c

### 構成＞全般設定＞ARR アフィニティOFF

> ステートレス アプリケーションの場合は、このオプションを [オフ] に設定できます。

https://docs.microsoft.com/ja-jp/learn/modules/configure-web-app-settings/3-configure-general-settings

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/260473dc-58d2-d0d7-97d0-ad14d2e4968e.png)


## その他

Azure App Serviceにデプロイしたアプリのサイズ比較

- [ASP.NET Core MVC Web アプリケーション](https://docs.microsoft.com/ja-jp/azure/cosmos-db/sql/sql-api-dotnet-application)：**90MB**
- 今回のBlazor Serverアプリ：**40MB**
知っていて当たり前−01　文字列の数値化

# 文字列を数値化

```Julia
parse(Int, "12345") # 12345
```
```Julia
parse(Int, "0x234") # 564
```
```Julia
parse(Float64, "123.45") # 123.45
```

```Julia
parse(Int64, "12abc", base=16)           # 76476
(((1 * 16 + 2)*16 + 10)*16 + 11)*16 + 12 # 76476
```

# ドット記法で複数の文字列を整数化

```Julia
parse.(Int, [string(12453)...]) # [1; 2; 3; 4; 5]
```

```Julia
parse.(Int, split("12345", "")) # [1; 2; 3; 4; 5]
```

```Julia
parse.(Int, ["123", "456"])   # [123; 456]
```

```Julia
x, y = parse.(Int, ["123", "456"])
print("$x, $y")               # 123, 456
```

# 2 個の数をスペースで区切ってキーボードから入力

```Julia
x, y = parse.(Int, split(readline())) # "12 345" を入力
x, y              # (12, 345)
```

```Julia
x, y = parse.(Float64, split(readline())) # "3.45 6.78" を入力
x, y              # (3.45, 6.78)
```
viewファイルを分割して外部化する（@extends）

# @extendsとは？

対象のbraid.phpファイルのコードをそっくりそのまま全て引き継ぎます（継承）

viewで表示させるbraid.phpファイルは
ヘッダー、メイン、フッターなど各要素で各々のbraid.phpファイルを作成し
親ファイルで合成して表示させる、外部化を推奨しております

@extendsは全てのコードを引き継ぐ（継承する）ため
HTMLタグのメタ要素を含むテンプレート（braid.phpファイル)を
親要素に引き継ぐ際に使用します。




#### 以下のようなメタ要素を含むテンプレート（braid.phpファイル)が存在する場合
```php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>@yield('title')</title>
</head>
<body>
  @yield('content')
</body>
</html>
```

#### @extendsでbraid.phpファイルの中身を呼び出す（継承する）ことができます

```php
{{-- layoutsフォルダのapp.blade.phpを呼び出す（継承） --}}
@extends('layouts.application')
```

共通するレイアウトを外部化することで
エラーが発生した際にも、エラー箇所を絞り込みやすく
コードの更新作業もしやすいため、メンテナンス性が上がります
Diodon で Ubuntu22.04 の Clipboard を履歴対応する

環境
- Ubuntu 22.04 ja LTS AMD64

履歴から Clipbpard を貼れるようにしたい。

# Clipit が動作しない

Ubuntu では Clipit というものが定番らしいが、 apt でインストールして起動してもすぐ終了してしまう。

最初の起動時に以下のメッセージが出てきたが読まずにOKを押したらそのまま終了してしまい、以降何も出ずに終了するようになった。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2e91fa35-d2e9-c569-5df0-a877d94a8944.png)

~/.config/clipit/disabled を削除すると再度出るようになったので読んでみると Diodon を使えとある。

# Diodon 


@matoken さんの
「Debian sidでサポートの終了したクリップボードマネージャーのClipItをDiodonに乗り換える &#8211; matoken&#039;s meme」
https://matoken.org/blog/2020/05/11/switch-the-deprecated-clipboard-manager-clipit-to-diodon-on-the-debian-sid/

同様に、情報を見てみると、以下のようになってました。

```
$ apt show diodon
Package: diodon
Version: 1.12.0-1
Priority: optional
Section: universe/utils
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Oliver Sauder <os@esite.ch>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 1,100 kB
Depends: libdiodon0 (= 1.12.0-1), zeitgeist-core (>= 0.9.14), dconf-gsettings-backend | gsettings-backend, libayatana-appindicator3-1 (>= 0.5.3), libc6 (>= 2.34), libglib2.0-0 (>= 2.46), libgtk-3-0 (>= 3.22), libpeas-1.0-0 (>= 1.1.1)
Homepage: https://launchpad.net/diodon
Download-Size: 68.2 kB
APT-Manual-Installed: yes
APT-Sources: http://jp.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
Description: GTK+ Clipboard manager
 Diodon is a lightweight clipboard manager for Linux written in Vala which
 "aims to be the best integrated clipboard manager for the Gnome/Unity desktop".
 .
 Diodon features include Ubuntu indicator, clipboard sync (primary selection
 and Ctrl+C / Ctrl+V clipboard) and a zeitgeist integration for an infinite
 clipboard history.

```

## インストール

```

$ apt install diodon

```

でインストールできました

## 起動

起動するとデスクトップ上右にゼムクリップのアイコンが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/07bbe2d2-e4bc-76ef-b4df-5e7d9065bff8.png)

クリックすると履歴が見えました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c946f46d-365a-0c48-5c92-bcd44192bfb7.png)


# ずっと過去の履歴を使う

過去の履歴は画面外にはみ出て使えないことがあります。その場合は、アプリ画面で参照できます。


diodon  を起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/dc1f1579-aa51-1164-7660-e06d51caad1a.png)

履歴リストが表示され、スクロールで過去のものが見えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e432ca96-d22d-41b0-12c8-2331a0aa955e.png)

# 履歴保持数を変更したり、画像を履歴に保持したりする

アプリ画面から履歴リストを出し、一番下の「設定」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/bdfa188a-3415-df3d-1f52-85a43896c68f.png)

履歴保持数などを設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b2be81f4-24bb-f2d6-3339-e3dc05bece57.png)
GolangのホットリロードはAirを使おう

# はじめに
Go言語で開発時にライブリロード機能がないと毎回コンテナを落としてあげてが面倒だった。調べてみるとAirを導入するとライブリロードが使えるみたいなのでその導入方法をメモとして残しておきます。
```Dockerfile
FROM golang:1.18-alpine

RUN apk update &&  apk add git
RUN go install github.com/cosmtrek/air@v1.29.0
WORKDIR /app

CMD ["air", "-c", ".air.toml"]
```
上記の`.air.toml`は[公式のもの](https://github.com/cosmtrek/air/blob/master/air_example.toml)を一旦そのまま持ってきています。カスタマイズしたい方は色々カスタマイズして見てください。

続いて`docker-compose.yml`は以下のように記述します。
```yaml
version: '3.8'
services:
  server:
    build:
      context: ./server
      dockerfile: Dockerfile.server
    container_name: websocket_server
    ports:
      - "8080:8080"
    volumes:
      - ./server:/app
```
ライブリロードがちゃんと機能していることを確かめるためにサンプルファイルを配置します。

```go
package main

import (
	"fmt"
	"net/http"
)

func say_hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, World!")
}

func main() {
	http.HandleFunc("/", say_hello)
	http.ListenAndServe(":8080", nil)
}
```
ここまでファイル構造は以下のようになっているはずです。
```shell
$ tree
.
├── README.md
├── docker-compose.yml
└── server
    ├── Dockerfile.server
    ├── go.mod 
    └── main.go
      
```shell
上記の状態でコンテナを起動し、以下のような画面になればAirの導入は完了です。
```shell
$ docker-compose build
$ docker-compose up server
docker-compose up server
[+] Running 1/1
 ⠿ Container websocket_server  Created                                     0.0s
Attaching to websocket_server
websocket_server  |
websocket_server  |   __    _   ___
websocket_server  |  / /\  | | | |_)
websocket_server  | /_/--\ |_| |_| \_ , built with Go
websocket_server  |
websocket_server  | mkdir /app/tmp
websocket_server  | watching .
websocket_server  | !exclude tmp
websocket_server  | building...
websocket_server  | running...
```

一旦Airの動作を確認しましょう。まずは上記の状態で[localhost:8080](http://localhost:8080/)にアクセスし、`Hello, World!`と表示されていることを確認します。
![](https://storage.googleapis.com/zenn-user-upload/65659f835340-20220731.png)


確認後に`main.go`を編集し、`Hello, World!`が`Hello, abemaru!`になっていればライブロードの設定が完了していることがわかります。

```go
package main

import (
	"fmt"
	"net/http"
)

func say_hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, abemaru!") // ここを変更
}

func main() {
	http.HandleFunc("/", say_hello)
	http.ListenAndServe(":8080", nil)
}
```
![](https://storage.googleapis.com/zenn-user-upload/5642ff9dbcc2-20220731.png)


ちなみに、ターミナルなどでairのログをみると、`main.go`が変更されていることをちゃんと検知していますね。
```shell
websocket_server  | main.go has changed
websocket_server  | building...
websocket_server  | running...
```

# さいごに
ライブリロードがあると開発が捗るのでどんどん開発していこう

参考
- https://zenn.dev/ajapa/articles/bc399c7e4c0def
- https://qiita.com/sogafish/items/69cd70ec2660a8335bfc
CSSで餅を描いてみる

書く内容がPythonに偏っていたので、たまには違うことをやりたいなと。
とりあえずCSSでイラスト作れたら嬉しいなと思ったので、簡単な絵を描いてみました。

## 餅
餅がぷくっと膨れている様子や焦げ目などは難しいので却下。鏡餅らしきものをさくっと作ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/4e507ca6-d866-9730-ceb5-83b890aa0a9b.png)

```mochi.html
<head>
<link href="mochi.css" rel="stylesheet">
<div class="bottom">
<div class="middle"></div>
<div class="top"></div>
</div>
</head>
```

```mochi.css
.bottom {
  width: 300px;
  height: 100px;
  line-height: 100px;
  background-color: white;
  border-radius: 100vh;
  border: solid 2px black;
  position:relative;
  top: 300px;
  left:110px;
}

.middle {
  width: 250px;
  height: 100px;
  line-height: 100px;
  background-color: white;
  border-radius: 100vh;
  border: solid 2px black;
  position:absolute;
  top: -105px;
  left:22.5px;
}

.top {
    width: 100px;
    height: 100px; 
    background-color: orange;
	border-radius: 50%;
	position:absolute;
	top: -205px;
	left:100px;
}
```

## 最後に
さくっと描いたといいながら、意外と苦戦しました。
2つの線分の交差判定（python）

## 背景
[問題解決のための「アルゴリズム×数学」が基礎からしっかり身につく本](https://gihyo.jp/book/2022/978-4-297-12521-9)の演習問題にて、2つの線分（4点が与えられたとき）の交差判定を行うプログラムを書いたので、今後の参考のためにまとめました。

- [対象の演習問題](https://atcoder.jp/contests/math-and-algorithm/tasks/math_and_algorithm_ah)

## この記事で説明しないこと
以下のサイトに「線分が交差するとは」といった説明やその判定条件についてまとめられているため、この記事では割愛いたします。

すごくざっくりとまとめると、以下です。
- 「交差する」とは、一方の線分を直線にしたとき、もう一方の線分が分断される、それが相互に成り立つか
- 領域を用いて条件の判定が可能。分断されているかは式の積が0未満かで判別できる。 

```math
y1 - ax1 -b < 0 \\
y2 - ax2 -b > 0 \\
(y1 - ax1 -b)(y2 - ax2 -b) < 0
```

### 参考サイト
1. [【Python】線分交差判定のプログラムを書いた](https://www.st-hakky-blog.com/entry/2018/09/05/012837)
2. [☆もっと簡単に－線分交差判定－☆
](http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm)

## 本題
上記の参考サイト１の実装例では、今回の演習問題ではACが取れません。
その理由として、2つの線分が１直線上にあるときや端が重なっているときに、問題側では交差と見做していることが挙げられます。

そこで、x座標、y座標ごとに座標が一切被っていない場合はfalseを返す処理を追加しました。
具体的な処理はそれぞれの最大値と最小値を比較し、最大値 < 最小値の時にfalseを返すというものです。
以下、4点[xi, yi]の座標が与えられたときの実装例です。

```py
A = list(map(int, input().split()))
B = list(map(int, input().split()))
C = list(map(int, input().split()))
D = list(map(int, input().split()))


def max_min_cross(p1, p2, p3, p4):
    min_ab, max_ab = min(p1, p2), max(p1, p2)
    min_cd, max_cd = min(p3, p4), max(p3, p4)

    if min_ab > max_cd or max_ab < min_cd:
        return False

    return True


def cross_judge(a, b, c, d):
    # x座標による判定
    if not max_min_cross(a[0], b[0], c[0], d[0]):
        return False

    # y座標による判定
    if not max_min_cross(a[1], b[1], c[1], d[1]):
        return False

    tc1 = (a[0] - b[0]) * (c[1] - a[1]) + (a[1] - b[1]) * (a[0] - c[0])
    tc2 = (a[0] - b[0]) * (d[1] - a[1]) + (a[1] - b[1]) * (a[0] - d[0])
    td1 = (c[0] - d[0]) * (a[1] - c[1]) + (c[1] - d[1]) * (c[0] - a[0])
    td2 = (c[0] - d[0]) * (b[1] - c[1]) + (c[1] - d[1]) * (c[0] - b[0])
    return tc1 * tc2 <= 0 and td1 * td2 <= 0


ans = "No"
if cross_judge(A, B, C, D):
    ans = "Yes"

print(ans)

```

この実装で、2つの線分として4点が与えられたときの線分の交差判定の問題は（おそらく）解けるかと思います。

## まとめ
線分の交差判定（というより主に数直線が交わってるかの判定）について記載しました。
似たような問題を解いている方の少しでも力になれれば幸いです。

ここまでお読みいただきありがとうございました。
今日気が付いたこと

Java Bronzeの資格取得に向けて、いわゆる黒本で勉強しています。

勉強中にいままで知らなかった点をメモしたくて記事を投稿していきます。

・ifのカッコ内がtrueの場合は、波カッコ｛｝の中の処理を実行する。
if(trueもしくはfalse){処理内容}
Goのdeferがよくわかならなかったので写経した

# はじめに
Go言語を最近少しずつ触っている中で`defer`が出てきたのですが、調べただけでは動きがわかりづらかったので触ってみることにしました。この記事は触った記録をメモしたものです。

```shell
$ go version
go version go1.18.4 darwin/arm64
```

# deferとは
deferはreturnされるまで実行されない書き方です。
例として以下のコードを考えます。
```go
package main

import "fmt"

func main() {
        defer func() {
                fmt.Println("defer")
        }()
        for i := 0; i < 10; i++ {
                fmt.Println(i)
        }

}
```
上記のように書いた場合、defer内の`fmt.Println("defer")`はfor文の後に実行されます。
```shell
$ go run main.go
0
1
2
3
4
5
6
7
8
9
defer
```

複数の`defer`を定義したときは以下のような挙動をします。
```go
package main

import "fmt"

func main() {
        defer func() {
                fmt.Println("defer 1")
        }()
        defer func() {
                fmt.Println("defer 2")
        }()
        defer func() {
                fmt.Println("defer 3")
        }()

}
```
いわゆるLIFO(Last In First Out)になっていることがわかります。
```shell
$ go run main.go
defer 3
defer 2
defer 1
```

for文に入れて実行してみると
```go
package main

import "fmt"

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

        for i := 0; i < 10; i++ {
                defer fmt.Println(i)
        }

        fmt.Println("done")
}
```
後ろから順番に実行されますね。
```shell
$ go run main.go
counting
done
9
8
7
6
5
4
3
2
1
0
```

# さいごに
deferはreturnの直前に実行される関数でした。

用途は、必要なくなったファイルを閉じたり、チャネルを閉じたり、プログラムのパニックをキャッチするために使用されるみたいです。

確かにwebsocketのコードで初めてみたのでなんとなくイメージはあっているのかもしれない。
Bash で雑 Exponential Backoff

Bash で雑に Exponential Backoff したくなって作ったので書いておく。

## 実装
``` sh:exponential_backoff.sh
#!/bin/bash -eu

if [ $# -eq 0 ]; then
    echo -e "Usage:\n  ${0} command"
    exit 1
fi

for((i=0;;i++)); do
  $@
  [ $? -eq 0 ] && exit
  echo "command execution failed"
  echo "wait $((2**i)) seconds and retry"
  sleep $((2**i))
done
```

終了コードが 0 以外なら sleep してリトライするだけの素朴な実装。

## 使い方
リトライしたいコマンドの例として「[0-9]の終了コードをランダムに返す (10回に1回くらい成功する) スクリプト」を用意。

``` sh:command.sh
#!/bin/bash -eu

code=$(($RANDOM % 10))

echo "status code: ${code}"

exit ${code}
```

`exponential_backoff.sh` を使って実行する。

``` console
$ ./exponential_backoff.sh ./command.sh
status code: 7
command execution failed
wait 1 seconds and retry
status code: 1
command execution failed
wait 2 seconds and retry
status code: 3
command execution failed
wait 4 seconds and retry
status code: 7
command execution failed
wait 8 seconds and retry
status code: 4
command execution failed
wait 16 seconds and retry
status code: 0
```

## 備考
ポートフォワーディングしている SSH 接続が切れたらリトライしたくて書いたけど、そんなことするより [autossh](https://www.harding.motd.ca/autossh/) 使ったほうが早い。
WARNING: UNPROTECTED PRIVATE KEY FILE!

下記コマンドを実行しようと思った結果
```
git push -u origin main
```

・エラー発生

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/sasakiyuuya/.ssh/github' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/sasakiyuuya/.ssh/github": bad permissions
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

何やら、権限が0644でオープンすぎると、秘密鍵ファイルに他の人がアクセスできないよにする必要があると、、、
そのため、リモートリポジトリが読み取れない

権限設定が必要とのこと、

chmod コマンドを実行

参考サイト
https://qiita.com/ntkgcj/items/6450e25c5564ccaa1b95

解決方法
・鍵のパーミッションを0600にしてあげるといいらしい。
```
chmod 0600 ~/.ssh/github
```

エラー解消
PowerAutomate: Teams のトリガー＆アクションでメッセージへのリンクは body/webUrl で

# 背景
一年以上前、Teams のアクションで対象メッセージへのリンクの取得方法を質問されて
「WebUrl」で取れますよーって返しただけで、例を示してなかったので理解されてなかったことがあった

ということで、簡単とはいえ、リンクはこうやって取れますよ、という例です。

伝わってなかった方々は、他のアクション使ったりして合成してたんです・・反省 :hushed: 

# 結論

トリガーなら、以下を貼り付け

```json: トリガー用
@{triggerOutputs()?['body/webUrl']}
```

アクションなら、こんな感じ

webUrl と messageLink の差異があるのかは不明。l と # とかの差異があれば・・とか思うんですけどねぇ


```json: アクション用 Get_message_details の例
@{outputs('Get_message_details')?['body/webUrl']}
```

```json: アクション用 Get_message_details の例２
@{outputs('Get_message_details')?['body/messageLink']}
```

:::note info
[Get_message_details](https://docs.microsoft.com/en-us/connectors/teams/#get-message-details)
日本語 ⇒ [メッセージ詳細を取得する](https://docs.microsoft.com/ja-jp/connectors/teams/#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E8%A9%B3%E7%B4%B0%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)
:::

# フローでの実践例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/1a4cbf75-dd88-fda3-d0d7-dc78c7340a41.png)

# ドキュメントも最新ではない

[When a new channel message is added](https://docs.microsoft.com/en-us/connectors/teams/#when-a-new-channel-message-is-added) の Return と実際の取得結果の比較

2年以上前から webUrl も使えてる筈だが
今もドキュメント反映されてない＆動的コンテンツに出てこない、ので、知らないと見つけにくいかも？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9891a3a3-0622-f57e-9d9e-10a71bd2baea.png)

# あとがき
人に伝える時は、やっぱり例を見せないとって改めて思いました。

「人に伝える唯一の手段は、例である」 by アインシュタイン
【batch】mp3ファイルのナンバリング 

カーオーディオでUSBを使って音楽を聴く場合、
曲順がぐちゃぐちゃになってることが結構ある・・・:joy:

プレイリストをitunesで*.m3uでエクスポートし、
メルセデスのCOMANDシステムに入力したが、
プレイリストの曲順をうまく認識せず・・・:joy:
ということで、batでmp3ファイルに直接ナンバリングすることに

私は3曲毎にジングルを入れる変わった聞き方をしてますので、
ナンバリングと同時に3曲毎にジングルも入れるbatを設計。
999曲までは下記で対応できる。

フォルダ、データ構成は下図の通り(jingleフォルダにジングル10曲を用意)
![number1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/7c4217d3-e9e4-6302-8150-83dfe983fc95.png)

```bat:numbering.bat
@echo off
setlocal enabledelayedexpansion
rem タイトル用曲順
set num=0
rem 3曲毎にジングル入れ
set remainder=3
rem ジングル選択カウンタ
set jno=0
rem CMループ用カウンタ
set CMcount=0
rem 全体ループカウンタ
set count=0
rem タイトル
set title=0

erase test.log

for %%f in (*.mp3) do (
set /a num=CMcount+count

	if !remainder! equ 0 (
		rem CMカウンタ＋1
		set /a CMcount=CMcount+1
		set /a jno=jno+1
		rem CMコピー
		set /a title=num
		rem 桁数調整
		if 99 geq !title! ( 
			if 9 geq !title! (
				set title2=00!title!
			) else (
				set title2=0!title!
			)
		) else (
			set title2=!title!
		)

		rem ---------------------------------------
		echo CMtitle=!title2! --!count!-->>test.log
		copy jingle\jingle_!jno!.mp3 .
		ren jingle_!jno!.mp3 !title2!_jingle_!jno!.mp3

		rem 曲名ナンバリング
		set /a title=num+1
		rem 桁数調整
		if 99 geq !title! ( 
			if 9 geq !title! (
				set title2=00!title!
			) else (
				set title2=0!title!
			)
		) else (
			set title2=!title!
		)
		rem ---------------------------------------
		echo 曲title=!title2! !count!>>test.log
		ren "%%f" !title2!_"%%~nf".mp3

	) else (
		rem 曲名ナンバリング
		set /a title=count+CMcount

		rem 桁数調整
		if 99 geq !title! ( 
			if 9 geq !title! (
				set title2=00!title!
			) else (
				set title2=0!title!
			)
		) else (
			set title2=!title!
		)
		rem ---------------------------------------
		
		echo 曲title=!title2! !count!>>test.log
		ren "%%f" !title2!_"%%~nf".mp3

	)

set /a count=count+1
set /a num=num+1
set /a remainder=count%%3
	rem ジングル10曲をループ
	if !jno! equ 10 (
		set /a jno=0
	) else (
		set /a jno=jno
	)

)
endlocal
pause
```

上記を実行し、下図のように曲の頭にナンバリングしてあげることでCOMANDシステムでも認識可。かつ、ジングルも3曲毎にローテで入っている
![number2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/f251a493-bd22-ff32-5d03-a9abd2c1febd.png)
【Rails】importmap-railsの注意点

# 初めに

Rails7 では、`importmap-rails`が標準で利用できるようになりました。

`webpacker`や`jsbuilding-rails`などと違い、javascript モジュールをブラウザに直接インポートされます。

`importmap-rails`は他と違い注意しないといけない点があるので、忘備録として記事にしておきます。

# 注意点

## パッケージの追加の仕方

`importmap`は javascript パッケージを追加するためには、以下のようにします。

```console
$ bin/importmap pin [パッケージ名]
Pinning [パッケージ名] to [パッケージURL]
```

といった形で、パッケージを追加していきます。
`importmap`で利用できるのは npm から取得できるパッケージ JavaScript CDN 経由で利用できるものだけです。

## JSX は利用できない

`webpack`のようにコンパイルなどを行わなず、ブラウザに直接インポートされます。
なので、`JSX`のような明示的なトランスパイルやコンパイルのステップが必要である場合は`importmap-rails`では利用できない。

## パッケージのアップデート

`npm update`などのようにパッケージをまとめてアップデートできませんが、下記のようなコマンドを使うことで新しいバージョンが存在するかを確認できます。

```console
$ ./bin/importmap outdated
新しいバージョンのnpmレジストリをチェックします

$ ./bin/importmap audit
既知のセキュリティ問題についてnpmレジストリをチェックします
```

## パッケージをローカルにインストールする

`--download`オブションを指定することで、パッケージをローカルにインストールできます。

```console
bin/importmap pin [パッケージ名] --download
```

`vender/javascript`ディレクトリにインストールされる。

# 参考

- [importmap-rails - github](https://github.com/rails/importmap-rails)
- [Rails 7: importmap-rails gem README（翻訳） - TechRacho](https://techracho.bpsinc.jp/hachi8833/2022_06_29/112183)
【ゲーム紹介】無料でクライアントサーバー型のゲームを制作する１

# ゲーム紹介
蜂を操作して制限時間内にできるだけたくさんの花の蜜を集めるゲームです。
![ミツあつめ3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664789/829f84ed-b892-66e2-a9f2-3d851a51cb78.gif)
左右の矢印キーまたはボタンクリックで蜂を動かします。
落ちてくる「おはな」に触れるとポイントゲットです。
![ミツあつめ2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664789/67919da1-7d80-57a3-c973-7321952345d8.gif)
天敵の「とり」に触れると集めた「おはな」ポイントが0になってしまいます。
![ミツあつめ4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664789/d4ac2eb3-15d4-f0b0-3bf5-1a23f5704cb7.gif)
30秒でゲーム終了です。
スコアをランキングに登録しましょう。
![ミツあつめ1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664789/2e68edbb-ce9c-316f-734d-1fdfef50128e.gif)
ユーザーデータは保存されており、以降はハイスコアの場合のみランキングに登録できます。

# 使用アセット
* [にくまるフォント](http://www.fontna.com/blog/1651/)

# 制作記事
* [【環境構築】無料でクライアントサーバー型のゲームを制作する２](https://qiita.com/kappysan/items/0fa9079468197780d712)
* [【サーバー】無料でクライアントサーバー型のゲームを制作する３](https://qiita.com/kappysan/items/a0e7d0f928797d569e72)
* [【クライアント】無料でクライアントサーバー型のゲームを制作する４](https://qiita.com/kappysan/items/3f9fd102fb872cc98656)

# GitHubリポジトリ
* [クライアント用](https://github.com/kappy-gh/Sample_Client/tree/master)
* [サーバー用](https://github.com/kappy-gh/Sample_Api/tree/master)
AH00558: apache2:  Could not reliably determine the server's fully qualified domain name,  が出ていたが、解決した。

# はじめに
apache2ctl configtestを実行すると、
AH00558: apache2: 
Could not reliably determine the server's fully qualified domain name, 
が出ていたが、解決した。

# 最終更新日
2022年8月1日

# 環境の情報
OS
Ubuntu20.04

# 注意
最新の状態を確認して下さい。

# 公式さまはこちら
https://www.apache.org/
https://httpd.apache.org/docs/2.4/programs/apachectl.html

# 参考さまはこちら
https://www.kishiro.com/apache/config_syntax_check.html
https://mk-55.hatenablog.com/entry/2014/07/07/004510
https://www.yokoweb.net/2020/08/14/ubuntu-20_04-apache-php/

# 状況

文法チェックすると、エラーが出た。

```
/etc/apache2/sites-available$  sudo apache2ctl configtest
AH00558: apache2: 
Could not reliably determine the server's fully qualified domain name, 
using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK
```

# 意味
:::note info
公式から
configtestの意味
Run a configuration file syntax test. 
It parses the configuration files and either reports Syntax Ok or detailed information about the particular syntax error. 
This is equivalent to apachectl -t.

設定ファイルの構文のテストをします。
:::


# やったこと

移動する。
```
/etc/apache2/sites-available$ cd /etc/apache2/conf-available/
```

設定ファイルが何があるか確認する。
```
/etc/apache2/conf-available$ ls
charset.conf                other-vhosts-access-log.conf  serve-cgi-bin.conf
javascript-common.conf      php7.4-fpm.conf
localized-error-pages.conf  security.conf
```
fqdn.confを作る。
```
/etc/apache2/conf-available$ sudo vi fqdn.conf
```
fqdn.confの内容をこんな感じで作る。
```
/etc/apache2/conf-available$ cat fqdn.conf 
ServerName 127.0.1.1 
```
fqdnを有効化する。
```
/etc/apache2/conf-available$ sudo a2enconf fqdn
Enabling conf fqdn.
To activate the new configuration, you need to run:
systemctl reload apache2
```  
Apache2を再びスタートさせる。
```
/etc/apache2/conf-available$ sudo service apache2 restart
```


# そして

再び、configtestを実行する。
エラーは無くなった！やったね！

```
/etc/apache2/conf-available$ sudo apache2ctl configtest
Syntax OK
```
Excelの計算式が反映されない問題

# Excelの計算式が反映されない問題
Excelの出力処理を行なっていると、今までは反映されていた計算式が反映されないという問題が起きました。
しかし、セル上でエンターを押すと計算式が反映されます。(えっ)

どうやら計算式が計算されない時があるみたいです。

## 解決法
出力を行う前に
```
Workbook.setForceFormulaRecalculation(true);
```
これをしてあげると、ファイルを開いた瞬間に再計算され、計算式が反映されます。

## 終わりに
謎な現象だったのでハマるかと思いましたが、意外とすぐ解決することができました。
しかし一緒に開発していた方がハマっていたようで、解決法を聞かれたのでPOIでハマる部分なのかと思い投稿しました。
どうか役に立つと嬉しいです。
PLATEAU関係のツール（converterなど）


# FME 
https://github.com/Project-PLATEAU/Data-Conversion-Manual-for-3D-City-Model
3D都市モデルのデータ変換マニュアル
https://www.mlit.go.jp/plateau/file/libraries/doc/plateau_doc_0007_ver01.pdf

#  3d-tiles-validatorの環境構築
https://github.com/CesiumGS/3d-tiles-validator
https://github.com/CesiumGS/3d-tiles-validator/tree/main/tools
 -> ❗️ 3D Tiles Tools is not actively maintained. For converting source data to 3D Tiles check out Cesium ion. ❗️
↑　メンテしていない。


先にnodejs をインストールしておく


# Validator
コマンドラインで、3d-tiles-validator\tools\binに移動して、
node ./bin/3d-tiles-validator.js b3dmToGlb -i ./specs/data/data1.b3dm -o ./extracted.glb
UNSUPPORTED_EXTENSIONになり、glbの出力もありません。

```
 "code": "UNSUPPORTED_EXTENSION",   
"message": "Cannot validate an extension as it is not supported by the validator: 'CESIUM_RTC'.",  
```

# PLATEAU tutorial
https://github.com/Project-PLATEAU/plateau-streaming-tutorial
https://github.com/Project-PLATEAU/plateau-streaming-tutorial/blob/main/3d-tiles/plateau-3dtiles-streaming.md

# 参考
https://www.docswell.com/s/smellman/ZW31XZ-2022-04-22-154703#p14

# EPSGコード一覧表/日本でよく利用される空間座標系（座標参照系）
https://lemulus.me/column/epsg-list-gis#i

# converter glm
https://gunmagisgeek.com/blog/
https://github.com/Jennyshining/3d-tiles-tools
https://elfrank.github.io/3d-file-converter/
https://github.com/elfrank/3d-file-converter  nodejs
https://github.com/CesiumGS/3d-tiles-validator/tree/main/tools#b3dmtoglb

https://github.com/fanvanzh/3dtiles
　：　中国製

https://gitlab.com/Oslandia/py3dtiles : 有望

# sample data
https://github.com/CesiumGS/3d-tiles-samples/tree/main/1.0/TilesetWithDiscreteLOD

# ECEF -> WGS84(BLH) 変換
https://www.mk-mode.com/blog/2021/05/12/cpp-convert-ecef-to-blh/
AUTOSAR（Adaptive Platform R22-11）を読む準備

まだ、出ていないAUTOSAR（Adaptive Platform 22-11）を読んでいくための準備を記録する。

# 1. 準備

AUTOSAR（Adaptive Platform 18.10）を読んでいく（1）

https://qiita.com/kaitotiak/items/9dba2083fe11406fefd8

を拝見し、準備なく読んでも、準備して読んでも、最後は同じところにたどり着くかもしれないと。どういう読み方をしたらいい、どういう読み方をしてはいけないということはない。　

それぞれ立場が違えば、同じ文字列であっても意味が違う。同じ文字列でもコンパイラによってエラーになるコンパイラもあれば、エラーにならないコンパイラもあるような感じ。

文字列が同じであれば、意味も同じだという主張は、一つの立場としてあるかもしれない。　
別の立場では、文字列が同じであっても、意味が同じとは限らないという立場もあることを配慮していただけると幸いです。


### Adaptive Platform Release Overview, 782

https://www.autosar.org/fileadmin/user_upload/standards/adaptive/21-11/AUTOSAR_TR_AdaptivePlatformReleaseOverview.pdf

どの文書から読んでもいいとする。

Referenceが空なのはいただけないかもしれない。文書中にはISOを参照している。

ISO 23150:2021
Road vehicles — Data communication between sensors and data fusion unit for automated driving functions — Logical interface

https://www.iso.org/standard/74741.html

Adaptive Platform Release Overview, No.782, AUTOSAR 21-11 (16) AP


https://qiita.com/kaizen_nagoya/items/e622ba8f9011344bd04a

Glossary No.55, AUTOSAR R21-11(1) FO

https://qiita.com/kaizen_nagoya/items/9eaf0c2a82a39c356f92

Autosar R19-11 Glossary

https://www.autosar.org/fileadmin/user_upload/standards/foundation/21-11/AUTOSAR_TR_Glossary.pdf

そうだ、Adaptive Platformは、Foundationの上に成り立つ。どちらを先によまなきゃいけないということはない。　


AUTOSAR 「完全に理解した」

https://qiita.com/kaizen_nagoya/items/51983798ad7902b33cb1

A big wrapping cloth with the miniature garden

https://qiita.com/kaizen_nagoya/items/96411f20632e7f3ff73a

Network Defined Vehicle

https://qiita.com/kaizen_nagoya/items/a696f8a8cbd141215266
【#45 エンジニア転職学習】GinTutorialのWebApp改造 GetPostFormについて

Fomr# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

GoのフレームワークであるGinを中心に、
webアプリ開発学習をしていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
GinのTutorialで作成したAPIを改造して、簡素なWebアプリを作成しようと思います。
昨日POSTできなかった原因が分かりましたので、その内容をまとめます。

* **GinのGetPostFormについて　←Topics!!**


# GinのGetPostFormについて
昨日投稿したコード
https://qiita.com/Chika110/items/e65f1cddac4fe6976ee6
のPOSTやPUT実行時、こちら側で設定したカラムのレコード値がMySQL側に渡っていませんでした。
結論から言うと、`gin.Context`の`GetPostForm`メソッドでJSONを読み込めないことが原因でした。

#### 対策
body情報を渡す際の`Content-Type`を`x-www-form-urlencoded`にする
#### 原因
Requestのbodyから情報を取得してくる`gin.Context.GetPostForm`に対して、POSTメソッドで`Content-Type:applicataion/json`のデータを渡していた。


~~~webserver.go
func (h *AlbumHandler) PostAlbums(c *gin.Context) {
	title, _ := c.GetPostForm("title")
	artist, _ := c.GetPostForm("artist")
	price, _ := c.GetPostForm("price")
	floatprice, _ := strconv.ParseFloat(price, 64)
	h.Db.Create(&models.Album{Title: title, Artist: artist, Price: floatprice})

	c.Redirect(http.StatusMovedPermanently, "/albums")
}
~~~

##### 使用している教材はこちら↓


https://go.dev/doc/tutorial/web-service-gin


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
ConoHa VPSで借りたサーバーにブラウザでアクセスして"ERR_CONNECTION_REFUSED"と出たら…

ファイアーウォールの設定を確認してください。
http接続用ポート(80)とhttps接続用ポート(443)が開いておらず、そのせいでアクセスが拒否されている可能性があります。

```conf:環境
Ubuntu 22.04 LTS
```

手順①既に開いているポートの確認
```terminal
#コマンド
sudo ufw status

#結果
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

```
手順②アクセスを許可するポートの追加
```terminal
#コマンド
sudo ufw allow http

#結果
Status: active

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
```

同じように`sudo ufw allow https`を実行してあげると`443/tcp`も追加されます。

ちなみに、設定を書き換えたら`sudo reboot now`などでサーバーを再起動しないと変更が反映されないかも。私はそうでした。
warning: unable to access '/Users/xxx/.config/git/ignore': Permission denied

ローカルからGitHudに繋げようと思ったら障害が起こった。

```
cd ~/
ls -al
```
上記コマンドw打つと、ファイルが数多く並ぶ、その中で.configファイルのところがrootになっている。


そうしたら下記コマンドを実行

```
sudo chown -R $(whoami) .config
```

.configファイルの所有権限を現在のユーザー名に変更する。

エラー解消。
AWS日記45(AWS Lambda - Layer)

# はじめに
今回はAWS Lambdaの[レイヤー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-layer)を試します。
[Lambda レイヤーの作成と共有](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html)を参考に、Lambda関数で使用するライブラリを作成します。

# 動機
Lambda関数実行時に以下のエラーが発生し、エラー解決のため レイヤーにライブラリを設定しました。
```bash
/var/task/bootstrap: error while loading shared libraries: libXXXXX.so.1: cannot open shared object file: No such file or directory
```

# ライブラリのzipファイルを作成
```bash
zip -r lib.zip lib/
```


# レイヤーの作成

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/9fe5367b-e73c-acab-72d5-a5f5f945e202.jpeg)

 - 名前、 zipファイル、 互換性のあるアーキテクチャ、 互換性のあるランタイムを設定します
![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/85637b17-f227-8567-513d-c9b5861bfde4.jpeg)


![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/f33ba11e-c445-d431-0bd1-62dac893ef13.jpeg)


##### zipファイルが大きすぎる場合、サイズ上限超過でエラーが発生します
![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/3dc8623a-023e-a1fb-7c66-d86aed8034a5.jpeg)



# Lambdaにレイヤーを設定

 - Lambda設定画面の最下部にスクロールします
![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/fcc7f3a5-8c87-1f78-ebb0-a70b92841fc2.jpeg)

 - 作成済みのレイヤーを指定します
![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/bedd719f-1cb6-80fb-1140-5c502fb3c345.jpeg)


##### 合計サイズが大きすぎる場合、サイズ超過でエラーが発生します
![08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/ee0fcdfa-8a81-805b-58da-adb60656d562.jpeg)



# 終わりに
AWS Lambdaのレイヤーを試しました。
CloudFormationで[AWS::Lambda::LayerVersion](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-layerversion.html)を設定する方法もあるので、今後試していこうと思います。
郵便番号検索jquery.jpostal.jsの実装

# 概要
郵便番号から住所を検索し、結果をセットするjsの実装をしてみました。
今回使用したのは、"jquery.jpostal.js"

https://github.com/ninton/jquery.jpostal.js/#%E8%A8%AD%E7%BD%AE%E6%96%B9%E6%B3%95b

# 環境
* Rails7
* ActiveAdmin

# 導入方法
本家を参照のこと。

環境内で動作させたかったので、郵便番号データ(json)はプロジェクト内に配置しました。
* public配下にjson配置
`public/jpostal_json`

* assets配下でもOKでした(追記)
`assets/jpostal_json`

# コード

```app/assets/javascripts/admin/active_admin.js
//= require jquery.jpostal.js
//= require admin/postalcode
```

```app/assets/javascripts/admin/postalcode.js
$(function () {
  $("#nursing_facility_user_post_code").jpostal({
    postcode: ["#nursing_facility_user_post_code"],
    address: {
      "#user_prefecture": "%3",
      "#user_municipality": "%4",
      "#user_subsequent_address": "%5",
    },
    url: {
      http: "/jpostal_json/",
      https: "/jpostal_json/",
    },
  });
});
```
urlパラメータはpublic配置した場合。
assetsの場合は、こちらでいけるかも(未検証)
```
url: {
   http: "assets/jpostal_json/"`
```

変更イベントの検知には`trigger`を使えばよいみたい。
```
	$('#postcode1').jpostal({
        ・・・
		trigger : {
			'#address1_kana'  : true,
			'#address2_kana'  : true,
			'#address3_kana'  : false
		}
	});

	$("#address1_kana").on("change", function() {
	    var val = $("#address1_kana").val();
	    val = "onchange_" + val;
	    $("#address1_kana_onchange").val(val);
	});

```

https://github.com/ninton/jquery.jpostal.js/blob/master/sample_1.html
Airflow資料抄訳(18)：クロス・コミュニケーション（XComs）



恥ずかしながら最近になって知ったワークフローエンジン [Apache Airflow](https://airflow.apache.org/)。日本語の紹介記事もちらほら出てきていますが、[公式ドキュメント](https://airflow.apache.org/docs/)をちょっとずつ抄訳しながら読んでいこうと思います。

18目の今回は[クロス・コミュニケーション](https://airflow.apache.org/docs/apache-airflow/stable/concepts/xcoms.html)（XComs）。
バージョン2.3.3時点のものです。

---

# クロス・コミュニケーション（XComs）

XComs（"cross-communications" の短縮形）は[タスク](https://airflow.apache.org/docs/apache-airflow/stable/concepts/tasks.html)同士が互いに情報のやり取りをするための仕組みです。デフォルトでは、タスク同士は完全に分離されており、まったく異なるサーバー上で実行される可能性もあります。

XComsでやり取りされる個々の情報は`key`（実質的にそれ自身の名前です）と、データソースとなる`task_id`および`dag_id`により指し示されます。（シリアライズ可能なものなら）どんなものでもやり取りできますが、仕組みとしてはあくまでも小規模なデータをやり取りするためだけに設計されたものです。この仕組を大規模なデータ、例えばデータフレームのようなものの送信に利用しないでください。

XComsにデータを追加するには`xcom_push`メソッドを、取り出すには`xcom_pull`メソッドを使用します。多くのオペレーターは` do_xcom_push `引数に`True`（デフォルト）が指定された場合、実行結果を` return_value`というキーで自動的にプッシュします。`@task`デコレーターで修飾された関数も同じように機能します。

`xcom_pull` メソッドはキーを指定せずに呼び出すと、この`return_value`をデフォルト値として利用します。これは次のようなコードを書くことができるということです：

```py
# "pushing_task"タスクが"return_value"というキーで登録した値を取り出す
value = task_instance.xcom_pull(task_ids='pushing_task')
```

XComsは[テンプレート](https://airflow.apache.org/docs/apache-airflow/stable/concepts/operators.html#concepts-jinja-templating)の中でも利用できます： 

```jinja
SELECT * FROM {{ task_instance.xcom_pull(task_ids='foo', key='table_name') }}
```

XComsは[変数](https://airflow.apache.org/docs/apache-airflow/stable/concepts/variables.html)（variables）に似ています。大きな違いはXComsがタスクごとに用意されるものであり、DAG Runの内部でのやり取りのために設計されているのに対して、変数はグローバルであり、Airflowの全般的な設定や値の共有のために設計されているという点です。

:::note Warn
Note
最初のタスクが成功しなかった場合、当該タスクのリトライの都度XComsはクリアされます。これはタスク実行を冪等なものとするためです。
:::

## カスタムXCom バックエンド

XComsのバックエンドは変更できます。設定ファイルの` xcom_backend `の項目で指定します。

独自のバックエンド実装を行いたい場合は、`BaseXCom`クラスのサブクラスを作成し、` serialize_value  `メソッドと` deserialize_value `メソッドをオーバーライドします。

この他に` orm_deserialize_value `メソッドもありますが、これはXComオブジェクトをWeb UI上で表示するときに呼び出されます。XComsを使って巨大なオブジェクトや、値を取得するのに大きなコストがかかるオブジェクトを扱っている場合、Web UIの応答速度を維持するために、このメソッドをオーバーライドしてデフォルトのコードが呼びされないよういしなくてはなりません（オーバーライドは軽量で、巨大なXComオブジェクトの一部分だけを表示するものになるでしょう）。

`clear`メソッドもまたオーバーライドできます。このメソッドを使用して特定のDAGとタスクの結果をクリアすることができます。このメソッドをオーバーライドすることで、カスタムXComバックエンドがデータ・ライフサイクルを処理するのが容易になります。

## コンテナ内でカスタムXComバックエンドを利用する

（省略）

## Helmで管理されたk8sクラスター内でカスタムXComバックエンドを利用する

（省略）

---

小規模なデータのやり取りにのみ使うように注意しつつ、大規模なデータをやり取りする場合のカスタムXComについて触れているあたり、、、現実には本来の目的を無視した使われ方がまあまあ横行しているのでしょうか。

このカスタムXComというのがどれくらいニーズがあるものなのか？　「コンテナ内で～」「k8sクラスター内で～」というところはこのカスタムXComが前提で、それなりに複雑なことを述べているようす。ただ今回は読まず。
Laravel ✖️ MySQL ✖️ Docker 新しいDatabaseを作成しよう

Laravel ✖️ MySQL ✖️ Dockerの環境構築は以下の資料を参考に構築しました。一度構築してしまえば、git cloneなんかで開発環境をローカルに再度取り入れることができるので便利です。

https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4#%E5%8B%95%E4%BD%9C%E7%92%B0%E5%A2%83

しかし、新しいアプリを作ろうとなった時、データベースを新規に作成したいってなるんですよね。

記事内にその方法が記載されていなかったので、実装してみました。

そのためには、知っていないといけない知識があるのでご紹介します。



## ボリューム(Data Volume)とは

ボリュームとは、Dockerコンテナにおいて生成され利用されるデータを、永続的に保持する目的で利用される仕組み。

### コンテナ と ボリューム の違いについて
- コンテナ内部にデータ(ファイル)を保存しても、コンテナ破棄すると消えてしまう。
- なので、データを永続化したいときは、コンテナの外にデータを置く必要がある。その場所のことを、ボリュームと呼ぶ。

ここからは新しいDatabaseを作成していきます。


<br>
<br>

## データベース名、パスワード、ユーザー名の変更。


### infra/mysql/Dockerfile
```docker
FROM mysql/mysql-server:8.0

ENV MYSQL_DATABASE=変更するデータベース名 \
  MYSQL_USER=変更するユーザー名 \
  MYSQL_PASSWORD=変更するパスワード \
  MYSQL_ROOT_PASSWORD=変更するパスワード \
  TZ=Asia/Tokyo

COPY ./my.cnf /etc/my.cnf
RUN chmod 644 /etc/my.cnf
```


```
[mac] $ code src/.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=変更するデータベース名
DB_USERNAME=変更するユーザー名
DB_PASSWORD=変更するパスワード
```

```
[mac] $ vim src/.env.example
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=変更するデータベース名
DB_USERNAME=変更するユーザー名
DB_PASSWORD=変更するパスワード
```


<br>

## Docker volume 削除
docker volume lsと打つと、現在のコンテナ内のvolumeを確認することができます。
```
 % docker volume ls
DRIVER    VOLUME NAME
local     docker-laravel-handson_db-store
local     laravel_environment_db-store
```

### volumeの削除
新規にデータベースを作成するにあたって、現在のvolumeを削除します。
<font color="Red">※docker のコンテナが動いている時にやるとエラーを起こすします。必ずコンテナを停止してからやること</font>

```
% docker volume rm docker-laravel-handson_db-store
% docker volume rm laravel_environment_db-store
```

<br>

## Dockerの再ビルド
```
docker-compose up -d -build
```

<br>

## マイグレーション実行
```
$ docker-compose exec php bash
```
```
root/data# php artisan migrate   
```
ここでマイグレーションができていれば、MySqlに新しいデータベースが作成されていると思います。


<br>

## マイグレーション時のエラー
私が実際に遭遇したエラーです。

```
root/data# php artisan migrate

QLSTATE[HY000] [1045] Access denied for user (using password: YES) (SQL: select * from information_schema.tables where table_schema = ~ and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:712
    708▕         // If an exception occurs when attempting to run a query, we'll format the error
    709▕         // message to include the bindings with SQL, which will make this exception a
    710▕         // lot more helpful to the developer instead of just the database's errors.
    711▕         catch (Exception $e) {
  ➜ 712▕             throw new QueryException(
    713▕                 $query, $this->prepareBindings($bindings), $e
    714▕             );
    715▕         }
    716▕     }

      +33 vendor frames 
  34  artisan:37

```

Dockerの再ビルド時にdocker compose up -d でビルドしてしまったことが原因でした。
以下のコマンドで
```
% docker compose down --volumes --rmi all
% docker compose up -d --build
```
設定ファイルがない状態でMySQLの初期化が行われたでデータが永続化されてしまってるので一度ボリューム毎削除してビルドし直せばokです。

<br>
<br>

## 参考資料

https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4#%E5%8B%95%E4%BD%9C%E7%92%B0%E5%A2%83

https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32
OpenAPI API仕様書の作成からコード自動生成までやってみた

# はじめに

OpenAPIを触る機会があって
* API仕様書の作成
* API仕様書からコードの自動生成

を行ったのでその際にやったことを備忘録も兼ねてまとめます。

# API仕様書の作成

API仕様書を作成するにあたってOpenAPIを使用します。
ただ実際動かすまでに以下のような側面があります。

* 環境構築が少し面倒
* 環境構築できるまでOpenAPIがどういったものかイメージしづらい

なので、
[Swagger EditorのWeb版](https://editor.swagger.io/)
が実際に触って動かせるのでオススメです。

コードの横にプレビュー表示してくれて、
かつ非同期で更新してくれるのでAPI仕様書はこれ見ながら作成しました。

``` yaml:openapi.yml
swagger: '2.0'
info:
  description: >-
    This is a sample server Petstore server.  You can find out more about    
    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
    #swagger](http://swagger.io/irc/).      For this sample, you can use the api
    key `special-key` to test the authorization     filters.
  version: 1.0.0
  title: Swagger Petstore
  termsOfService: http://swagger.io/terms/
  contact:
    email: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
host: petstore.swagger.io
basePath: /v2
tags:
  - name: pet
    description: Everything about your Pets
    ...略
```



# API仕様書からコードの自動生成

API仕様書からコードの自動生成を行うにはOpenAPIGeneratorを使用しました。

OpenAPIGeneratorを使用する方法は、いくつかありますが今回はnpmを使用しました。
（[公式GitHubのREADME](https://github.com/OpenAPITools/openapi-generator)で使用方法の一覧と方法が乗ってます）

※npmで使用する場合、JVMが必要だったので[Java 17](https://www.oracle.com/java/technologies/downloads/#jdk17-windows)をインストールしてます。

### ①npmでopenapi-generatorをインストールします
```
npm install @openapitools/openapi-generator-cli
```

### ②以下のような感じでコードを自動生成します

```
openapi-generator-cli generate -g <ジェネレーター> -i <生成元ファイル> -o <生成先のフォルダ>
```
-g : 生成するコードの種類を指定（[ジェネレータ一覧](https://openapi-generator.tech/docs/generators)）
-i :「API仕様書の作成」で使用したyamlファイル/xmlファイルを指定
-o : 自動生成されるコードの出力先を指定

### ③オプションでコードの自動生成をカスタマイズ

使用頻度高そうなオプションをピックアップして紹介します。

**1. --global-propertyオプション**

自動生成するコード群を指定たり、逆に生成しないコードを指定することもできます。
[global-property一覧](https://openapi-generator.tech/docs/globals/)で指定できるプロパティを一覧で見れます。

```
# 実際こんな感じ
openapi-generator-cli generate -g <hoge> -i <hoge> -o <hoge> --global-property models
openapi-generator-cli generate -g <hoge> -i <hoge> -o <hoge> --global-property=apiDocs=false,modelDocs=false,...
```


**2. -s, --skip-overwriteオプション**

既存で同じファイルがある場合はそのファイルは上書きをしないオプションです。
[こちら](https://openapi-generator.tech/docs/usage/#generate)でgenerate時に指定できるoptionを一覧で見れます。

```
# 実際こんな感じ
openapi-generator-cli generate -g <hoge> -i <hoge> -o <hoge> --skip-overwrite
```

# まとめ
今回API仕様書の作成からコードの自動生成までの手順を半分備忘録で書きました。

* API仕様書の作成
* API仕様書からコードの自動生成

の流れが分かるようになってたなら幸いです:ramen:
# 参考

* [Swagger EditorのWeb版](https://editor.swagger.io/)
* [公式GitHubのREADME](https://github.com/OpenAPITools/openapi-generator)
* [openapi-generatorリファレンス](https://openapi-generator.tech/)
基本情報（ファイルと文書）

ワープロやら、表計算やら、アプリケーションソフトやら作成したデータは**ファイル**として**補助記装置**に記録されます。
使いたいとなった時にすぐに呼び出すことができないので、プログラムというファイル形式で補助記憶装置にしまわれています。

## データの種類と代表的なファイル形式
共通フォーマットとして広く利用されているファイル形式には下記があります。
### テキスト形式
文字コードと、改行やタブなど一部の制御文字のみで作られるファイル形式です。文字を扱うアプリケーションソフトであれば、まず間違いなく読み書きすることができます。
### CSV形式
基本的にはテキスト形式ですが、個々のデータである文字や数字をカンマ(,)で区切り、行と行を改行で区切ることで、表形式のデータを保存することに特化したファイル形式です。
### PDF
画像が埋め込まれた書類を、コンピュータの機種やOSの機種によらず、元の通りに再現して表示することができる電子文書のファイル形式です。文書配布時における標準的なフォーマットとなっています。
###  画像用のファイル形式
|   |説明  |
|---|---|
|BMP  |画像を圧縮せずにそのまま保存するファイル形式。画質は一切劣化しないが、ファイルサイズは大きくなります。  |
|JPEG  |写真を保存するのに向いている画像圧縮形式です。圧縮率が高く、フルカラーの画像を扱えるため、ディジタルカメラで写真を記録する用途などでも使われています。不可逆圧縮を行うため、圧縮のレベルに応じて画質が劣化します。  |
|GIF　 | イラストやアイコンなどの保存に適した画像圧縮形式です。可逆圧縮であるため画質の劣化はありませんが、扱える色数が256色までという制限を持ちます。
|PNG |当初はGIFの代替として登場しましたが、フルカラーを扱える上に可逆圧縮であるため画質の劣化もないという、万能な画像圧縮形式です。|
### 音声用のファイル形式
|   |説明  |
|---|---|
|MP3  |音声を圧縮して保存するファイル形式。不可逆の圧縮を行う。MP4の方がよく見る  |
|MIDI  |音声そのものではなく、ディジタル音楽の演奏データを保村することができるファイル形式。最近あんまりみない |
### 動画用のファイル形式
|   |説明  |
|---|---|
|MPEG  |動画を圧縮して保存するファイル形式で不可逆圧縮。ビデオCDに使われるMPEG-1、DVDに使われるMPGE-2、インターネット配信や携帯電話で使われるMPEG-4など  |

## 個人的に気になったファイル形式その他
基本情報には書いてないが、ファイル形式という言葉を見て気になってしまったので書いておきます。

### TSV形式
CSVと違いタブで項目間を区切る。
```
csv
hoge,hoge,hoge

tsv
hoge  hoge  hoge
```

### XML形式
Extensible Markup Languageの略です。記述が冗長になりがちなので、jsonが使われることが多くなってきている
```
<要素名 属性名="属性値">内容</要素名>
```

### JSON形式
JavaScript Object Notationの略でjson。聞いたら最初は誰もが金曜日を思い浮かべる。オブジェクト構造をベースにして作成されており、軽量なため使われることが多い
```
{
    "hoge" : "fuga",
    "birthday : 1999,
}

// { "key" : "value" } の形式
```

## マルチメディアデータの圧縮と伸張
画像や音声、動画などのマルチメディアデータは、そのまま保存すると膨大なデータ量になってしまいます。そのため、何らかの圧縮技術を用いてデータサイズを小さくして保存するのが普通です。

圧縮されたファイルを開く時は、**逆方向の伸張**という展開作業を行なって、元のデータを復元します。元々のデータを間引く形で圧縮したものは、伸張後も厳密な意味の「元と同じ」データにはなり得ません。このような圧縮方法を**不可逆圧縮**と呼びます。戻せる場合は**可逆圧縮**と言います。

## まとめ
どこも大事