OmniAICreator/Qiita-1.07M huggingface dataset:
外部からTwitterのDM画面を立ち上げるURLを生成する

※2021/07/29 時点では挙動を確認済ですが、Twitterがいつ仕様変更するかは不明瞭なのでお気をつけください

```
- 利用されてないAPI等を切る傾向あり
- 昔はpublish.twitter.comの公式側でサポートあったが今はない…
```

## TL;DR

- 外部サイトとかから
- Twitterに連絡をもらいたいときに
- DMを立ち上げるURLを生成する方法

ユースケース：
![スクリーンショット 2021-07-29 23.48.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85776/9b1483f8-cb62-a20c-4a3a-bd644521872b.png)


## 前提

- DMを開放して受け取れる設定にする

### 設定方法

- もっと見る > 設定とプライバシー > プライバシーとセキュリティ > ダイレクトメッセージ > 「すべてのアカウントからのメッセージリクエストを許可する」にチェック

|Step1|Step2|
|---|---|
|![スクリーンショット 2021-07-29 23.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85776/ee897cdc-e8b4-ff63-27a7-abb64c30f660.png)|![スクリーンショット 2021-07-29 23.36.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85776/b87c9af0-176d-24ed-2539-7fdd01e5dcbb.png)|

## URLを準備する

### 完成形

```text
https://twitter.com/messages/compose?recipient_id={user_id}
```
の形でURLを用意する

例：https://twitter.com/messages/compose?recipient_id=786590689651896320

### user_id を把握するには

こちらの[TWITTER ID CONVERTER](https://commentpicker.com/twitter-id.php)から確認が可能

- 検索窓にHN(@hogehoge)を入力して
    - ※ `@`はつけてもつけなくもOK
- 返ってきた文字列がuser_id


```
※他人のIDも把握できるのですが、言わずもがな悪用は厳禁です
※以前はTwitterのサービス上から確認ができたのですが、どうやらできなくなってしまったようです(もしくは表示場所が変わってしまった)
```

## 利用したい箇所で利用する

- ブログ
- HP
- 求人記事
- Webサービス/App

などなど
[Rails]基本的なエラーを知ろう

# はじめに
本記事では、
私が体験したエラーや、
調べた結果、おそらく基本的なエラーを共有します。

# エラーの一覧

### Name Error
`定義されていない変数名`を利用した場合に発生。
このエラーが発生したら、変数名を打ち間違えていないか、
変数を定義し忘れていないか確認する。

### No Method Error
`メソッドを定義していない`ことで生じるエラー。
メソッドを定義している場所は、コントローラーであるため、
まず、各アクションのコードをみて、メソッドを定義しているかを確認する。

コントローラーにメソッドが定義されていた場合は、
コントローラアクションに関連したデータベース上のテーブルカラムを確認する。
カラムがなければ、カラムを追加する。

### Argument Error
メソッドの引数の数が合っていないときや、引数が空であるときに発生するエラー。
Argumentは、`引数`という意味。

### Routing Error
「受け取ったURL」と「コントローラー内のアクション」が関係していないためのエラー。
原因として、config/routes.rbにてコードの書き間違いであることが多い印象。

### Template is missing
コントローラーで設定しているアクションの
ビューが設定されていない場合に発生するエラー。

Railsでは、
「コントローラーのアクション名」と「ビューのファイル名」が
`同名称になる事が基本`で、
コントローラーのアクションとビューのファイル名に違いがある場合は
コントローラーで明示的に記載する必要がある。

# 終わりに
自分が体験し、
おそらく基本的なエラーはこの辺かと思い、
アウトプットとして記事にしました。

エラーが出たらとにかく調べることが大切だと思いますが、
基本的なエラーは知っておく方が対処が早くできるのではないかと思いました。

エラーは出ないのが、一番ですが、
エラーはいつになっても付き纏うものです。

逃げずに積極的にエラーに向き合いましょう！！！
スマートフォンアプリにおけるファイルの保存先

react nativeのアプリを書く時に、各OSごとに保存先の方針の違いに混乱したため、備忘録としてまとめました。

# iOSの場合
|判断基準  |具体例  |保存場所  |
|---|---|---|
|ユーザが作成した（一時的ではない）データ<br>アプリが再作成できないデータ<br>**ユーザに公開していいもの**  |ユーザデータ<br>ダウンロードした画像  | Application_Home/Document  |
|再ダウンロードできるデータ<br>再作成できるデータ<br>バックアップを取らなくていいもの |データのキャッシュファイル<br>ドキュメントデータ  |Application_Home/Library/Caches  |
|一時的にのみ使用されるデータ<br>勝手に消されても問題がないもの　|起動ごとに変わる一時的なデータ　|Application_Home/tmp|

- 一番上の項目だけが、iCloudバックアップ対象
- また、/tmpディレクトリのものはアプリが実行されていない時に、システムに勝手に削除される可能性があるので扱いに注意すること

# Androidの場合
※Androidは端末によってファイルの保存場所が異なるため、ファイルパスではなくアクセス手段としてまとめます

|判断基準|具体例|保存場所へのアクセス手段|
|---|---|---|
|アプリ固有のファイル|アプリ独自のデータ|内部ストレージからは getFilesDir() または getCacheDir()<br>外部ストレージからは getExternalFilesDir() または getExternalCacheDir()|
|他のアプリと共有するメディアファイル|他のアプリと共有する画像、音声ファイル|MediaStore API|
|ダウンロードしたファイル|DLした画像、音声ファイル|ストレージアクセスフレームワーク|
|アプリ設定|アプリの設定情報|Jetpack Preferences library|
|データベース|ローカルのデータベース|Room persistence library	|

- アプリの固有ファイルについて、外部ストレージにある場合は他のアプリからアクセスできるが、内部ストレージにある場合は他のアプリはアクセスできないので注意が必要
- アプリアンインストール時にはアプリ固有のファイル以外は削除されない
- 内部ストレージと外部ストレージの違い
    - 内部ストレージ
        - 外部ストレージに比べ容量が少ない
        - 全てのデバイスが利用可能→信頼性が高い
    - 外部ストレージ
        - 内部ストレージに比べ容量が大きいことが多い
        - Android9以前は権限が必要だった→Android10以降はデフォルトで付与されるようになった

# 参考
https://developer.apple.com/icloud/documentation/data-storage/

https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

https://developer.android.com/training/data-storage
RGBを用いて色を決める(UIColor)

# 今回の内容

* アプリを作ってる時に、どうすればカスタムされた色をコードで使えるのか気になったので調べてみました。

* `UIColor(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)`を用いて色を変えてみます。

#RGBとは 
* なんとなく分かりそうですが、Rは`Red`、Gは`Green`、Bは`Blue`です。

* この3色の組み合わせを用いて、さまざまな色を表示することが出来ます。

# コードと簡単解説

* 今回は、コードで作成したUISegmentedControlの`selectedSegmentTintColor`でカスタムした色を使いたいので、`UIColor(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)`を使用します。

* 今回は、この画像の赤い色を表示します
<img width="150" alt="228E7FD3-554A-4C93-BBCE-ADA4C04B2736_4_5005_c.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/0d874042-a9b0-65b8-1c68-00e1cbf4bae0.jpeg">

```Swift
   uiSegmentControl.selectedSegmentTintColor = UIColor(red: 1.0, green: 0.40, blue: 0.51, alpha: 1.0)
```

* ここで、`red: 1.0, green: 0.40, blue: 0.51, alpha: 1.0`の値を簡単に調べる方法を書きます
 * Main.storyboardにViewなどの色を設定できるものを作成します。
 
 * 色をcustomで選択します。(今回はViewのbackgroundColorに色を設定したと仮定)
 
 * viewDidLoadなどで`print(self.view.backgroundColor as Any)`を使用するとデバッグエリアに下記のように表示されます。
 
 * 左からRGBと一番右はalphaです。
 
 * 表示された数字の部分を四捨五入して使います。(例:0.405169を0.40にして使います)　

```Swift
   (UIExtendedSRGBColorSpace 1 0.405169 0.512318 1)
```

#実際のコード

```Swift
class SegmentedControl{

    var uiSegmentControl = UISegmentedControl()
        
    let realmCRUDModel = RealmCRUDModel()
    
}

extension SegmentedControl{
    
    func createSegment(targetView:UIView){
        
        realmCRUDModel.readRealmTag()
        
        uiSegmentControl.removeAllSegments()
        
        for segmentCount in 0...realmCRUDModel.realmTagArray.count - 1{
         
            uiSegmentControl.insertSegment(withTitle: realmCRUDModel.realmTagArray[segmentCount], at: segmentCount, animated: true)
            
        }
        
        uiSegmentControl.frame = CGRect(x: targetView.bounds.minX + 5, y: targetView.bounds.minY + 97, width: targetView.frame.size.width - 10, height: 32)
        
        uiSegmentControl.selectedSegmentTintColor = UIColor(red: 1.0, green: 0.40, blue: 0.51, alpha: 1.0) 
        
        targetView.addSubview(uiSegmentControl)
    }
    
}
```

# 終わり
Qiitaを書いてると無意識に書く内容を何回も呟いたり、考えたりするので
いつの間にか覚えてることが最近よくある
ご指摘、ご質問などありましたら、コメントまでお願い致します。
Parsonを使用してC言語でJSONファイルを出力

# はじめに
C言語でJSONを扱う方法を、備忘録として残します。

# JSONパーサをダウンロード
JSONパーサにはParson（[https://github.com/kgabis/parson](https://github.com/kgabis/parson)）を用いました。


# そもそもパーサとは？
パース（parse：解析する）するツールです。
JSONを扱うときに必要なプログラムと思ってください。

# 必要なファイルは2つだけ
Parsonをダウンロードできたら展開します。
必要なファイルは次の3つのみです。

- parson.h
- parson.c
- tests.c

他にもいろんなファイルがありますが、サンプルで使うファイルであったり、英語の説明書です。
必要に応じて読んでみてください。

# 具体的なプログラム
それでは、具体的なプログラムを見ていきましょう。

## parson.hとparson.cはそのまま使う
parsonを扱うために必要なヘッダファイルと、いろんな定義ファイルなのでそのまま使います。

## tests.cから必要な部分のみ残して書き換える
（test.cは初めから削除して、新しくスクリプトシートを作った方が良いかもしれません。かなり改変していますし…）

ここにmain関数が記述されています。
必要な部分を抽出し、コメントを加えて少し変更したプログラムを以下に示します。

```c
#include <stdio.h>
#include "parson.h"

int main(void)
{
    /* 初期化 */
    JSON_Value* my_value = json_value_init_object();
    JSON_Object* my_object = json_value_get_object(my_value);
    
    /* メンバをセット */
    json_object_set_string(my_object, "name", "John Smith");
    json_object_set_number(my_object, "age", 25);
    json_object_dotset_string(my_object, "address.city", "Cupertino");
    json_object_dotset_value(my_object, "contact.emails",
                             json_parse_string("[\"email@example.com\", \"email2@example.com\"]"));
    
    /* コンソールに表示 */
    char* serialized_string = NULL;
    serialized_string = json_serialize_to_string_pretty(my_value);
    puts(serialized_string);
    json_free_serialized_string(serialized_string);
    
    /* JSONからデータを抽出 */
    const char* name = NULL;
    name = json_object_get_string(json_object(my_value), "name");
    printf("Hello, %s.", name);
    
    /* JSON書き出し */
    json_serialize_to_file(my_value, "test_output.json");
    
    /* データ解放 */
    json_value_free(my_value);
    
    return 0;
}
```



# 出力データ
プログラムを実行後、コンソールにJSON形式で文字が出力されていたら成功です。
コンソールに出力されている文字と同じものがJSONファイルに出力されています。
構造はここで説明するよりも、自身で色々いじってみる方が理解できると思いますので、割愛します。

```c
{
    "name": "John Smith",
    "age": 25,
    "address": {
        "city": "Cupertino"
    },
    "contact": {
        "emails": [
            "email@example.com",
            "email2@example.com"
        ]
    }
}

```

# まとめ
JSONパーサ「Parson」を使用し、C言語でJSONを出力しました。
【備忘録】Lightning Experienceの基本

#Lightning Experienceの概要
Lightning Experience →　新salesforceインターフェースのこと。
（Salesforce Classic　→　旧salesforceインターフェース）

見分け方は右上を見て、
アイコンがある　→　Lightning Experience
アプリケーションメニューがある　→　Salesforce Classic

####Lightning Experienceを使用するメリット
1. 効率的なナビゲーションおよびカスタムブランドアプリケーション間の切り替え
2. 何が表示されるかではなく、何を実行できるかを重視した新しいレコードレイアウト
3. データを簡単に絞り込んで視覚化できる、瞬時に表示されるリストビュー
4. ユーティリティバーの [メモ] や [最近使ったデータ] などの生産性ツールへのクイックアクセス
5. 複数の列と行の両方にまたがるコンポーネントを含む洗練されたダッシュボード
6. すばやく絞り込んで最も重要なデータを表示できる、整然としたレポートビュー

##Lightning Experienceのホームでできること
・パフォーマンスグラフで目標達成までの進捗を確認する。
・ニュースを使用して、お客様、パートナー、競合他社に関連するニュース記事を遅滞なく閲覧する。
・ミーティングの予定や期日が本日の ToDo を確認する。
・アシスタントで今日取り組むべき主な問題を特定する。
・[最も重要な商談] で営業活動の焦点を絞る。

##Lightning Experienceの商談ワークスペースでできること
・重要な情報の表示
・活動の記録、Todoの作成、メールの迅速な送信
・コーチングの詳細とカスタマイズ可能なパスで、セールスプロセスをサポート
・豊富な関連情報をフロート表示
・取引先責任者と同様にコンテキストに関連レコードを追加
・商談に関連性が高いタイムリーなニュースを表示

##・・・のkanbanビューでできること
・各フェーズまたは状況で作業を視覚化する
・ドラッグアンドドロップ機能を使用して列間でレコードを移動する
・列と集計項目をその場で設定する
・レコードを編集または削除して、最新の状態に保つ
・目的に応じてデータを絞り込むための検索条件をすばやく作成できる
・商談の場合、重要な案件に対するアクションが必要になったらアラートを表示して通知する

#Lightning Experienceがもたらすメリット
###営業ユーザ
セールスプロセスが明確化される。
プロセスの段階ごとのサポートを受けられる。
メモをとる、電話をかける、メールを送る等がページを離れなくてもできる。

###サービスユーザ
複数のアプリケーションを切り替えなくていい
【Unity】iOS,Androidでuuidを取得する方法

## Android
`SystemInfo.deviceUniqueIdentifier`

## iOS
`SystemInfo.deviceUniqueIdentifier`
ではOSのアップデート時に値が変わるそうなので一工夫が必要です。

## 前提条件
iOSのキーチェーンを取り扱うアセットを使います。

https://assetstore.unity.com/packages/3d/characters/ios-keychain-plugin-43083?locale=ja-JP

## 手順
1.キーチェーンからuuidを取得する。
2.uuidがなければ「Guid.NewGuid()」でuuidを発行する。
3.発行したuuidをキーチェーンに保存する。

これでアプリを端末から削除しても変わらないuuidが使えます。


## サンプルソース

```cs
using UnityEngine;
using FSG.iOSKeychain;
using System;

public class TestManager : MonoBehaviour
{
    public static readonly string KEY_ID = "CustomID";

    void Start()
    {
        string id = string.Empty;

#if UNITY_IOS
        id = Keychain.GetValue(KEY_ID);

        if (string.IsNullOrWhiteSpace(id))
        {
            id = Guid.NewGuid().ToString();

            Keychain.SetValue(KEY_ID, id);
        }

#elif UNITY_ANDROID
        id = SystemInfo.deviceUniqueIdentifier;
#endif

        Debug.Log($"id : {id}");
    }
}
```
mermaid.js で UML(シーケンス図)を書く

# mermaid.js とは
UMLなどの図をテキストで記述できる JavaScriptのライブラリ

公式
https://mermaid-js.github.io/mermaid/#/

LiveEditor
http://mermaid-js.github.io/mermaid-live-editor/beta

StackEditでも使える
https://stackedit.io/app



# シーケンス図例
LiveEditorのサンプルより
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33343/9d20a129-362a-3e69-a81f-60f2b91b65e5.png)


上記の図のソース

```
sequenceDiagram
    Alice->>+John: Hello John, how are you?
    Alice->>+John: John, can you hear me?
    John-->>-Alice: Hi Alice, I can hear you!
    John-->>-Alice: I feel great!
```
【今日の学びメモ】JavaScript で Falsy な値を使った判定をする

JavaScript で

```js
A && B
```

と書いた場合、 **A** の値が **Falsy** だと **A** の値そのものが返ってくる。

例えば以下のような感じ。

```js
console.log(undefined && true);
>> undefined
```

返り値を`boolean`に固定したければ、否定演算子`!`を二つ重ねて

```js
console.log(!!undefined && true);
>> false
```

とすれば良い。

`undefined`ではなく`!!undefined`とする意味がわからなかったのでメモ。
【今日の学びメモ】flex と inline-block

# flex
親要素に指定。
子要素の上が揃う。
![スクリーンショット 2021-07-29 22.13.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748993/eb525a68-13e1-fa41-b0e0-e9d3629dd429.png)


# inline-block
子要素に指定。
子要素内の inline 要素の下が揃う。
![スクリーンショット 2021-07-29 22.14.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748993/d8a3c4fd-72ec-d135-da02-993f60ba7514.png)

ちゃんと調べたことがなかったのでメモ。
「三角形の頂点の座標から五心の座標を求める」を参考にWolframAlphaとSymPy Liveでやってみたい。

# オリジナル

https://qiita.com/Ebishu/items/6115f2364a2e5fab5e4d


# wolframalphaで
## 1.重心

?????

https://www.wolframalpha.com/input/?i=%E9%87%8D%E5%BF%83+&lang=ja

https://www.wolframalpha.com/input/?i=%E9%87%8D%E5%BF%83+%280%2C0%29%2C%283%2C0%29%2C%283%2C4%29+&lang=ja

結果:
{2, 4/3}


## 2.外心

https://www.wolframalpha.com/input/?i=%E5%A4%96%E5%BF%83+&lang=ja

https://www.wolframalpha.com/input/?i=%E5%A4%96%E5%BF%83+%280%2C0%29%2C%283%2C0%29%2C%283%2C4%29+&lang=ja

結果:
(3/2, 2) = (1.5, 2)

## 3.内心

https://www.wolframalpha.com/input/?i=%E5%86%85%E5%BF%83++&lang=ja

https://www.wolframalpha.com/input/?i=%E5%86%85%E5%BF%83+%280%2C0%29%2C%283%2C0%29%2C%283%2C4%29+&lang=ja

結果:
(2, 1)

## 4.垂心
勉強中
## 5.傍心
勉強中

# SymPy Liveで
以下のソースコードを貼り付けて、Evaluateです。

https://live.sympy.org/
## 1.重心
勉強中
## 2.外心
勉強中
## 3.内心
```python
from sympy import *
var("xA yA")
var("xB yB")
var("xC yC")
ABC = Triangle(Point2D(xA,yA),Point2D(xB,yB),Point2D(xC,yC))
I = ABC.incenter
I = I.subs({xA:0,yA:0,xB:3,yB:0,xC:3,yC:4})
print("#",I)
#
ABC = Triangle(Point2D(0,0),Point2D(3,0),Point2D(3,4))
I = ABC.incenter
print("#",I)
# Point2D(2, 1)
# Point2D(2, 1)
```
## 4.垂心
勉強中
## 5.傍心
勉強中


# 参考

https://qiita.com/HigashinoSola/items/2ab8894b543e0c55cfa7

https://qiita.com/fockl/items/ed06309f2642e70e04c1
【CircleCi】パイプラインを手動トリガーにする

## はじめに
CICD導入＋自分で１からAndroidアプリを作成しAppiumでE2Eテスト自動化をやってみて学んだことを備忘録として残しておく。
自分で１からAndroidアプリを作成してE2Eテスト自動化を行ったリポジトリは以下。

https://github.com/yuta-katayama-23/MobileAppE2ETest

## CircleCiのパイプラインのトリガー
### デフォルトの設定について
[^1]: https://circleci.com/docs/ja/2.0/triggers/#skip-builds
基本的にはVCSへのpushをトリガーにしてパイプラインが走るようになっている。
push時にパイプラインが走らないようにするには、`[ci skip]`とか`[skip ci]`という文字列をコミットメッセージ or 説明に記載すればいい。[^1]

>By default, CircleCI automatically builds a project whenever you push changes to a version control system (VCS). You can override this behavior by adding a [ci skip] or [skip ci] tag anywhere in a commit’s title or description.

### 手動でパイプラインを実行する
[^2]: https://circleci.com/docs/ja/2.0/triggers/#trigger-a-job-using-curl-and-your-api-token<br>https://circleci.com/docs/api/v2/#operation/triggerPipeline
手動のトリガーでCircleCiのパイプラインを実行したくなる場面も出てくるが、そんな時には、Web APIをcallすればいい。[^2]

```bash:sample.sh
curl https://circleci.com/api/v2/project/<vcs-type>/<org>/<repo>/pipeline \
  --request POST \
  --header "Circle-Token: <API_KEY>"
```

- `<vcs-type>`<br>CircleCiの`config.yml`を置いているVCSのタイプ<br>ex) github
- `<org>`<br>CircleCiのorganizationの名前
- `<repo>`<br>VCSのリポジトリ名（CircleCiのパイプラインでcheckoutするブランチのリポジトリ）
- `<API_KEY>`<br>CircleにアクセスするためのToken

また、この手動トリガー以外でパイプラインを実行させたくない場合には、yamlを以下のように記述し、curlコマンドも次のように変更する事でそれが実現できる。

```bash:sample.sh
JSON=$(cat << EOS
  {
    "branch": "main",
    "parameters": {
      "manual": true
    }
  }
EOS)

curl https://circleci.com/api/v2/project/<vcs-type>/<org>/<repo>/pipeline \
  --request POST \
  --header "Circle-Token: <API_KEY>"
  --header "Content-Type: application/json" \
  --data "${JSON}"
```
```yaml:sample.yml
version: 2.1

parameters:
  manual:
    type: boolean
    default: false

workflows:
  run_pipeline:
    when: << pipeline.parameters.manual >>
    jobs:
      - hoge
      - fuga
```

上記のような実装したソースコード（yaml）全体は以下。

- GitHub Actionsのyml（CircleCiのworkflowをキックするパイプライン）<br>https://github.com/yuta-katayama-23/MobileAppE2ETest/blob/happybirthday-app/.github/workflows/circleci-manual-start.yml
- CircleCiのyml（手動トリガーのみで実行されるように実装したパイプライン）<br>https://github.com/yuta-katayama-23/MobileAppE2ETest/blob/happybirthday-app/.circleci/config.yml#L10
命名に迷った時に使うアプリ

#はじめに
クラス名やモデル・カラムの名前に迷うときありませんか？

そんな時に出会ったアプリがあるので紹介します！

#codic

**codic**です！

https://codic.jp/

このクラス名英語でなんてすればいいのだろうと思ったときに使えます。![スクリーンショット 2021-07-29 22.13.35（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264460/250878bd-c398-cf89-d068-dde084ec5c6a.png)

普通の辞書ですやん！と思った方！

このアプリ`スネークケース`や`キャメルケース`など選ぶことができます。

すごい簡単な投稿になりましたが使い勝手がいいので投稿しました。
任意の空スタック受理式非決定性プッシュダウンオートマトンから等価な文脈自由文法を得る方法がわかりにくい

任意の空スタック受理式非決定性プッシュダウンオートマトンから、それに等価な文脈自由文法を得る方法がわかりにくいので、わかりやすく説明します。

# 前提の再確認
まず、今話したオートマトンは以下で定式化されます。

```math
M=(Q,\Gamma ,\Sigma , \delta, q_0,Z_0,\phi)
```
このオートマトンは、有限オートマトンに比べて、タプルの中の文字が二つ増えています。そちらを見てみましょう。
右端のφの位置は最終状態の集合が入る場所ですが、今回は最終状態が空なので空集合になっています。（空スタック、と対応。つまり、εで受理されるということ。）　また、$\Gamma$はスタック記号の集合です。
どちらも、プッシュダウンオートマトン独自の概念ですので、この点がわからなければ、教科書でその定義を確認してください

# 作成する非終端記号の形式が独特
さて、開始記号$S$以外に、どのような非終端記号を定めたら良いでしょうか。

今回のケースは、通常のオートマトンから文法への変換とは異なります。
それは、今回のプッシュダウンオートマトンでは、状態とスタック記号のペアを常に念頭におくという方針になっているからです。そのようなペアはモード$(p,A)$などと呼ばれることがありますね。 なお、ここでは、$p\in Q, A\in\Gamma $です。

さて、本題に入ります。S以外の非終端記号の定め方は以下です。
$(p,A)$から推移を繰り返して$(q,\epsilon)$となる、すなわち、空スタック受理となる場合を考慮して、以下のような非終端記号を定めます。

```math
　[p,A,q]   (p,q\in Q, A\in \Gamma, x\in\Sigma ^*)
```

この表記は$(p,Q)$, $(q,\epsilon )$のペアから$[p,A,q,\epsilon]$のような非終端記号を定めてもいいけど、εはいちいちかくのがめんどいので省略した、という理解で覚えてください。（あくまで覚え方です。）

# 具体的な非終端記号の作成及び生成規則の作成


## (I)初期のスタック記号と、初期状態に関する作業
(I) すべての$r(\in Q)$に対して、以下の生成規則を作る。


```math
S\rightarrow [q_0,Z_0, r]
```
これは数式そのままなのでわかりやすいです。

## (II) 状態推移関数の各結果に基づいた作業

ここが抽象的でわかりづらいと感じました。まず、教科書からの抽象的な定義を引用します。

/////引用/////

$\delta(p,a,A)\ni(q_1,B_1B_2...B_n)$ $(a\in\Sigma \cup {\epsilon}, B_i \in \Gamma)$である時、すべてのあらゆる可能な重複を許した組み合わせの$q_2,q_3,...,q_{n+!}$に対して、生成規則

```math
[p,A,q_{n+1}\rightarrow a[q_1,B_1,q_2][q_2,B_2,q_3]...[q_n,B_n,q_{n+1}]
```

を作る。特に、$\delta(p,a,A)\ni(q_1,\epsilon)$である時には、生成規則

```math
[p,A,q_1]\rightarrow a
```

を作る。

/////引用ここまで//////

後半はそのままなのでわかりますが、前半の「すべてのあらゆる可能な重複を許した組み合わせの....(大量の数式)」のくだりで、脱落します。

わかりやすく説明すると、

私「これから一つ一つ、順番に状態推移関数を見ていきましょう」
私「状態推移関数が返す結果で、スタック記号はεですか？つまり、空受理になってますか？」

**状態推移関数が返すスタック記号がεの場合**

私「ラッキーですね。入力aをそのまま矢印の向こう側に書いて一つの生成規則が完成です。」


**推移関数のスタック記号が１つだけあった場合**

私「それでは、状態推移関数が返すスタック記号は何個ありますか？」

```math
\delta(p,a,A)={(p,A)}
```

私「なるほど、一つですね。状態は全てを挙げると$p,q$なので、それらから１つずつ重複を許して選んだら$q_2=p$または$q_2=q$が得られますね。これが、さっきの複雑な定義式にあった組み合わせのことです。」
私「今回は、一つしか選べないので、簡単ですね。後は数式通りにやってください。」

**そうでなかった場合（推移関数のスタック記号が2つの場合）**

私「それでは、状態推移関数が返すスタック記号は何個ありますか？」

```math
\delta(p,a,A)={(p,AB)}
```

私「なるほど、２つですね。状態は全てを挙げると$p,q$なので、それらから2つずつ重複を許して選んだら$(q_2,q_3)=(p,p)$ $(q_2,q_3)=(p,q)$ $(q_2,q_3)=(q,p)$ $(q_2,q_3)=(q,q)$が得られますね。この全てについて先程のごちゃごちゃした生成規則の式にぶちこんで、４つの生成規則を作ってください」


ということで、まずは状態推移関数が返すスタック記号はεなのか確認。もしそうならラッキー！そうでなくても、状態推移関数が返すスタック記号の数に着目して、$p_i$を順序を考慮して埋めていってください。


以上、お読みいただきありがとうございました。明後日テストなので、寝ます。

# 参考
オートマトン・言語理論　森北出版
golangメモ

# 開発環境作成

バージョン
go version go1.16.5 linux/amd64     

一回目に起動する

```
docker run -it --name golang--workdir /working -v $PWD:/working golang bash     
```

2回目に起動する

```
docker start golang -i
```

#プロジェクトの初期化

```
go mod init sample
```

#実行ファイルの作成

```sample.go
package main

import (
    "fmt"
    "os"
    "time"

    "github.com/mmcdole/gofeed"
)

func main() {
    feed, err := gofeed.NewParser().ParseURL("https://zenn.dev/spiegel/feed")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    fmt.Println(feed.Title)
    fmt.Println(feed.FeedType, feed.FeedVersion)
    for _, item := range feed.Items {
        if item == nil {
            break
        }
        fmt.Println(item.Title)
        fmt.Println("\t->", item.Link)
        fmt.Println("\t->", item.PublishedParsed.Format(time.RFC3339))
    }
}
```

#モジュールのインストール
goにはGOPATHモードとモジュール対応モードがあり、デフォルトのモジュール対応モードを使う。

```
go mod tidy
```

#実行

```
go run sample.go
```


# 参考

https://hisa-web.net/archives/1056
https://zenn.dev/spiegel/articles/20201003-feed-with-golang
【備忘録】Google Formで入力した相手に自動でメールを送るスクリプト

## はじめに

とあるイベント（社外の完全ボランティア）を主催する際に、Google Formで入力いただいた相手にZoomのURLを送る運用をしましたが、当日直前でも参加したいという意思表示にも対応できるように、自動でZoomのURLを送れるようにGASで対応しました。

備忘用にスクリプトを記載します。

なお、自分以外のひと（＝IT未経験者）でもメンテナンスできるように、Google Formの回答スプレッドシートにスクリプト設定シートを作成し、ZoomのURLなどはシートに記載し、その値を取得する形を取っています。

![スクリーンショット 2021-07-29 21.40.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322052/89d14bd7-cd7e-69c9-bff9-4ba7bcfa523e.png)

[2021/07/30 修正]
メール本文(const body)をテンプレートリテラルに修正しました。
愚直に改行、文字結合をしなくてよくなりすっきりしました。

## コード

```javascript:send.gs
function onFormSubmit(e) {
  // フォームの回答を取得
  const name = e.namedValues['氏名'][0];
  const email = e.namedValues['メールアドレス'][0];

  // 紐づいているSpreadSheetの操作
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('スクリプト設定シート'); // シートを名前で指定して取得する

  const zoomUrl = sheet.getRange(4,3).getValue(); // c4セルの値を取得
  const mtgId = sheet.getRange(5,3).getValue(); // c5セルの値の取得
  const passCd = sheet.getRange(6,3).getValue(); // c6セルの（ry

  // 件名
  const subject = 'XXXXXイベントのご案内';
      
  // 本文
    const body =` ${name} 様

    XXXXXXでございます。

    この度はお申し込みいただき、誠にありがとうございました。

    イベントは
    mm/dd（w）hh:MM（日本時間）〜 にて行う予定です。
    詳しいスケジュール表は下記WEBサイトをご覧ください。
    URL：http://example.com

    ZOOM URL: ${zoomUrl} 
    Meeting ID: ${mtgId}
    passcode: ${passCd}
    
    なにかご不明点がございましたら、下記メールアドレスまでご連絡ください。
    以上よろしくお願いします。
    ────────────
    XXXXXイベント運営委員
    Email：event@example.com
    URL：http://example.com/`
    ;
  
  // メール送信
  MailApp.sendEmail({
    to: email,
    subject: subject,
    body: body
  });
}
```
【Qiita】ページ内リンクの設定

# サンプル
編集中に↑のリンク(鎖マーク)をクリックすると、URLが次のようになります。

```
https://qiita.com/drafts/~~~/edit
```

↓

```
https://qiita.com/drafts/~~~/edit#サンプル
```

以下のようにedit以降を設定すればよいです。

```
[サンプル](#サンプル)
```

[サンプル](#サンプル)
※記事が短すぎてスクロールしません…

()内の書き方にはルールがあるようですが、このようにすれば気にする必要もないのかなと思いました。
ipwhoisを使ってwhoisで得られる情報を得る

```
ykishi@dezembro X-Forwarded-For % cat whois_test.py 
```
```Python
#!/usr/bin/env python3

from ipwhois import IPWhois
import json
import sys


def get_info(ip):

  obj = IPWhois(ip)
  whoisInfo = obj.lookup_whois()

  # print(type(whoisInfo))

  name = whoisInfo["nets"][0]["name"]
  country = whoisInfo["nets"][0]["country"]

  return name, country


if __name__ == "__main__":

  result = get_info("51.103.36.90")
  print(type(result))
  print(result)
  print(",".join(result))
  print(result[0])
  print(result[1])
ykishi@dezembro X-Forwarded-For % ./whois_test.py 
<class 'tuple'>
('MICROSOFT', 'GB')
MICROSOFT,GB
MICROSOFT
GB
ykishi@dezembro X-Forwarded-For % 
```
EC-CUBE3でassets ファイルのコピー

## Filesystemのuse記載
``` php:
use Symfony\Component\Filesystem\Filesystem;
```

## コピー元とコピー先の指定

``` php:PluginManager.php
private $srcAssets = __DIR__ . '/Resource/assets';
private $dstAssets = '/my_plugin)'; // /{プラグインコード(全て小文字}
```

## コピー関数

``` php:PluginManager.php
private function copyAssets(Application $app)
{
    $file = new Filesystem();
    $file->mirror($this->srcAssets, $app['config']['plugin_html_realdir'].$this->dstAssets.'/assets');
}
```

## 削除関数

``` php:PluginManager.php
private function removeAssets(Application $app) 
{
    $file = new Filesystem();
    $file->remove($app['config']['plugin_html_realdir'].$this->dstAssets);
}
```

## PluginManger.php全体
```php:PluginManager.php
<?php

namespace Plugin\MyPlugin;

use Eccube\Application;
use Eccube\Plugin\AbstractPluginManager;
use Symfony\Component\Filesystem\Filesystem;

class PluginManager extends AbstractPluginManager
{

    private $srcAssets = __DIR__ . '/Resource/assets';
    private $dstAssets = '/my_plugin)';// /{プラグインコード(全て小文字}

    /**
     * プラグインインストール時の処理
     *
     * @param $config
     * @param Application $app
     * @throws \Exception
     */
    public function install($config, Application $app)
    {
        $this->copyAssets($app);
        $this->migrationSchema($app, __DIR__.'/Resource/doctrine/migration', $config['code']);

    }

    /**
     * プラグイン削除時の処理
     *
     * @param $config
     * @param Application $app
     */
    public function uninstall($config, Application $app)
    {
        $this->removeAssets($app);
        $this->migrationSchema($app, __DIR__.'/Resource/doctrine/migration', $config['code'], 0);
    }

    /**
     * プラグイン有効時の処理
     *
     * @param $config
     * @param Application $app
     * @throws \Exception
     */
    public function enable($config, Application $app)
    {
    }

    /**
     * プラグイン無効時の処理
     *
     * @param $config
     * @param Application $app
     * @throws \Exception
     */
    public function disable($config, Application $app)
    {
    }

    /**
     * プラグイン更新時の処理
     *
     * @param $config
     * @param Application $app
     * @throws \Exception
     */
    public function update($config, Application $app)
    {
    }

    /**
     * リソースファイルなどをコピー
     *
     * @param Application $app
     */
    private function copyAssets(Application $app)
    {
        $file = new Filesystem();
        $file->mirror($this->srcAssets, $app['config']['plugin_html_realdir'].$this->dstAssets.'/assets');
    }

    /**
     * コピーしたリソースファイルなどを削除
     *
     * @param Application $app
     */
    private function removeAssets(Application $app)
    {
        $file = new Filesystem();
        $file->remove($app['config']['plugin_html_realdir'].$this->dstAssets);
    }
}
GASを使って社内文書提出の効率化を図る

#効率化は正義ではないでしょうか

業務は極力効率化して、暇な時間に好きな調べ物をするのが正しい時間の使い方と信じています。
今回はGASを使用して社内文書の作成から提出までの効率化を図りました。
なお、情報の取扱い等については、自己責任で行ってください。

#全体の流れ

1. Google Formに必要な入力枠を用意する
1. 社内文書のテンプレート(excel)をGoogle Driveへアップロードする
1. Google Formに回答が入力されたら、内容をフォーマットに反映しPDF化＋自分のGmailからメール送信するようプログラムを実装する
1. フォームに入力されたらGASが動くようにトリガーを設定する

#Google Formに必要な入力枠を用意する
今回は週報を簡単にスマホから送れるように設定します。
名前や部署、日付などはすでに簡単な関数(today())やベタ打ちで解決済みですので、
毎週自力で書かなきゃいけない部分だけフォームに設定します。
こちらのサイトが非常にわかりやすかったです→[フォームを新規作成](https://www.g-workspace.jp/googleworkspace-reference/forms/create-form/#:~:text=1.%20%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%92%E6%96%B0%E8%A6%8F%E4%BD%9C%E6%88%90,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82)
![フォーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409578/1f37882e-b7d1-4e70-5cb3-93250b8afac2.png)

フォームを作成したら、ログを吐き出すよう設定します。

1. 左上の [回答] で、[概要] をクリックします。
1. 右上のその他アイコン その他次に [回答先を選択] をクリックします。
1. オプションを選択します。(新しい/既存のスプレッドシートを作成)
1. [作成] または [選択] をクリックします。


#社内文書のテンプレート(excel)をGoogle Driveへアップロードする
エクセルでアップロードしたものは、別名でGoogle SpreadSheetへ保存します


#実装したプログラム
アップロードした社内文書のテンプレートのIDとフォームと連携したIDを手元に控えておきます。
sampleプログラム中では以下の3種類のファイルの指定方法を用いていますので、間違えないようにします。

* ドライブ上のファイル名
* Google SpreadSheetのID*
* URL

※IDの調べ方：
①IDを知りたいシートを開く。
 ②URLの「 "… /d/" と "/edit#…" で囲まれた部分」がID　


以下のプログラムをのフォームのログ吐き出し先のSpreadSheetにスクリプトとして保存する。

```sample.gs

function myFunction() {
  //　回答ログ
  var spreadsheet_from = SpreadsheetApp.openById('フォームのログの吐き出し先のID');
  var sheet_from = spreadsheet_from.getSheets()[0];
  var lastrow = sheet_from.getLastRow();
  // テンプレート
  var spreadsheet_to = SpreadsheetApp.openById('テンプレートのID');
  var sheet_to = spreadsheet_to.getSheets()[0];

  var copyValue = sheet_from.getRange(lastrow,2).getValues();
  sheet_to.getRange('C5').setValues(copyValue);

  var copyValue = sheet_from.getRange(lastrow,3).getValues();
  sheet_to.getRange('A9').setValues(copyValue);

  var copyValue = sheet_from.getRange(lastrow,4).getValues();
  sheet_to.getRange('C21').setValues(copyValue);

  var copyValue = sheet_from.getRange(lastrow,5).getValues();
  sheet_to.getRange('C26').setValues(copyValue);

  var copyValue = sheet_from.getRange(lastrow,6).getValues();
  sheet_to.getRange('A32').setValues(copyValue);

  SpreadsheetApp.flush()
  var ss = SpreadsheetApp.openByUrl('https://テンプレートのURL/edit');

  // Googleドライブ上のfileを取得する
  var driveImage = DriveApp.getFilesByName("テンプレートのファイル名").next();

  MailApp.sendEmail({
    to: '自分のメールアドレス@gmail.com',
    //もちろん送信したい相手のアドレスを直接指定しても良いですが、私は一度自分あてに送ったものを転送する形で使用していました。
    subject: '週報の送付',
    body: '社長 \n 営業さん \n \n 週報をお送りいたします。\n ご査収ください。',
    attachments: [driveImage.getBlob().setName('テンプレートのファイル名')]
  });  
}
```

#トリガーを設定する
上記のスクリプトを設定したら、同時にトリガーも設定しましょう。

1. スクリプトエディタ内の時計アイコンをクリック
1. 右下のトリガーを追加をクリック
1. トリガーを設定
![トリガー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409578/9996b47d-13eb-aa53-1963-bec7df45b78e.png)

1. 画面に従って許可を進めていく

#おわりに
過去(n年前)に作ったものなので設定等が漏れていたらすみません。
多分以上で動作するかと思います。
通常の業務ではJavaScriptを使用していなかったり、調べながら作ったつぎはぎのプログラムだったりで、不具合やもっとこう書いたらよいなどがあれば是非教えてください。(2021/7/29　プログラム動作確認済み)
機会があれば更新していきたいと思っています。
Three.jsを使って動きのあるページを作成しよう！


![](https://i.imgur.com/GBp1kYs.jpg)

## 環境
- MAMP導入済み
- Visual Studio Code　設定済み

## 今回使用する言語
- HTML
- CSS
- JS

## 作業の目次
- １：各フォルダの作成
- ２：HTMLのコード作成
- ３：JSのコード作成
- ４：CSSのコード作成

### 1:各フォルダの作成
- 1.下記の画像のように、CSS / JS / img フォルダを作成しましょう！![](https://i.imgur.com/HsjCOWC.jpg)

### ２：HTMLのコード作成
- 1.threeJS_4.htmlファイルを作成!

![](https://i.imgur.com/cRN87ue.jpg)

- 2.head部分を作成しよう

![](https://i.imgur.com/KlCR8Kf.jpg)

３行目　<meta charset="utf-8" />を記入

４行目<link rel="stylesheet" href="css/Newstyle.css" type="text/css">を記入
ここではCSSフォルダ内のNewstyle.cssを読み込みます。

５行目　<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r127/three.min.js"></script>を記入
これを読み込むことで、Three.jsが使用できるようになります！

６行目<script type="text/javascript" src="js/Moon.js"></script>を記入
ここではjsフォルダ内のMoon.jsを読み込みます。

- 3.body部分を作成しよう
![](https://i.imgur.com/sVmmwNz.jpg)


９行目 div class="example"クラスの宣言

１０行目　nav class="regular"　クラスの宣言

１１〜１３行目　Ulタグ　liタグで作成

１４行目　/nav で閉じる

１６行目　<canvas id="myCanvas"></canvas>
ここでcanvasのidを宣言
このmyCanvasに対して、３Dアニメーションが効いてきます！

１７行目　pタグで表示したい文字記入今回はMoonと記入

以上でHTMLコードの作成完了

### ３：JSのコード作成
***- 1.ページの読み込み確認とサイズの指定***

![](https://i.imgur.com/9U97v5s.jpg)

ページの読み込みが完了してから４行目のfunction init() {　以降の処理を実行していきます！

6~7行目でページの大きさを決めます！

***- 2.レンダラーを作成しよう！***
※レンダラーとは仮想的な3D空間における物体を2Dのディスプレイに適切に描画するためのもの。

![](https://i.imgur.com/xMAVYPR.jpg)

１０行目のWebGLRendererとは：その名のとおり、WebGLを扱うレンダラーのことです。

***- 3.シーンとカメラの作成！***

![](https://i.imgur.com/CvYeF4y.jpg)

シーンとは：3D空間のことで、3Dオブジェクトや光源などの置き場のことです。

カメラとは：3D空間上での視点の位置を指します！

- 4.月と輪を作成しよう！

![](https://i.imgur.com/dKEOM71.jpg)

２６行目でmaterial（マテリアル）を作成します。
ここでは物体の色や質感または付与したい画像をロードします！

※月の画像は各自で用意してください。

３１行目でgeometry（ジオメトリ）を作成します。
主に、物体の形状を決めるものです。
例：球体・ドーナツ・キューブ

３４行目でmesh（メッシュ）を作成します。
これは、materialとgeometryの情報を元に物体を作るものです。

３６行目のmesh.position.set(300, 0.5, 0.5);は物体の初期位置を決めるものです。

３９行目のscene.add(mesh);でメッシュを3D空間に挿入します！

同じように、輪の形状のものを作成しよう！

![](https://i.imgur.com/eGNZZ7o.jpg)

- 5.光源を設置しよう！

※光源（ライト）とは、物体に対しての光の角度や、光の明るさ、を調整して陰影を作り出すものです。

![](https://i.imgur.com/Kp0l01Q.jpg)

５７行目：DirectionalLightクラスを定義

５８行目：directionalLightの初期位置を指定

６３行目：PointLightクラスの定義



- 6.星屑の作成！

７１行目：createStarField();で宣言

７３行目： function createStarField() 

97行目： tick();の中に今までの設定が入っていると考えてください！

![](https://i.imgur.com/dbHug1I.jpg)

- 7.物体に動きを与えよう！

![](https://i.imgur.com/VTtWmOA.jpg)

１００行目：tick()の配列の中に動きを入れます。

１０２〜１０３行目：X・Y方向に向かって回転させる速さむきを調整します。

１０７〜１１１行目：三角関数を元に。Sin/Cosを使ってライトの周回向きを調整する

１１４〜１１５行目：X・Y方向に向かって回転させる速さむきを調整します。

１１９行目：レンダリングを行う。

１２１行目：アニメーションの実行！



### ４：CSSのコード作成

![](https://i.imgur.com/KIAhlSU.jpg)

.example では位置を設定します！

.example  pではpタグ内の文字の設定をします！

navではnav要素全体の大きさや色合いを設定します！

nav ulでは行全体の設定をします！

![](https://i.imgur.com/7NzSuPl.jpg)

nav a ではaタグ内の文字の設定をします！

nav li a:hover ではaタグにカーソルを合わせた時のアクションを設定します。

myCanvasでは画面全体のデザイン、背景の設定もおこないます。
※背景となる銀河などの写真は自由です。


# 完成

- 以上でThree.JSによる作品の制作は完了です！

最後に下記のgitからコードをクローンして答え合わせをしましょう！
https://github.com/katayama502/TEST_ThreeJS
【UiPath】Excel - データテーブルの列がない場合に追加する

# はじめに

この投稿は、RPAツール「UiPath」の 実装例 の記事です。

UiPathのコミュニティ「UiPath Friends」が企画する「UiPathブログ発信チャレンジ2021サマー」の 29日目の投稿でもあります。

企画の内容は [**こちら**](https://note.com/shumpei_w/n/n651cbdbec4e8) 。カレンダーのURLは [**こちら**](http://u0u1.net/sUwZ) です。

https://twitter.com/ShumpeiWatanabe/status/1405168150736359427


# 処理結果を書き込むシートがない時

ロボットの仕様として「処理結果をファイルに追記していく」パターンがあります。
処理結果を書き込むファイルは、以下のようなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/dc923a53-6b87-c8ed-2abc-a46a1dfb1370.png)

この仕様の時に「初回実行時は結果ファイルがない」ため、書き込む列名の定義が分からず困ります。

その場合、以下の方法で対応します。

```
1）ヘッダーだけのファイルを事前作成する（手作業）
2）ヘッダーだけの「雛型シート」を用意し、シートコピーして作る
3）xaml内の「データテーブルを構築」アクティビティ内で定義を作成する
4）設定ファイルに「列名一覧」を用意して、データテーブルの列を自動拡張させる
```

私は今まで、上記の1か3を採用していたのですが、最近は4で対応しています。

1や2の場合「ファイルを削除されしまい困る」ケースがあります。
また、仕様変更で列名が増えた場合に、昔のシートから作るとエラーになります。
3の場合は「データテーブルを構築」アクティビティを変更するのが手間です。

要は1、2、3のやり方だと「列の項目追加」仕様変更時にトラブルになりやすいのです。
<br>
4の方法ですが、具体的には以下のようにします。

1）設定ファイルに結果ファイルの列名の一覧を用意する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/ed6ec6bb-cc3e-5645-54a2-a19e861f60e1.png)


2）設定ファイルの列名一覧と比較し、無い列を自動で追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b9143d09-9bc0-bdbb-a421-94f87e2ce645.png)

こうすることで「初回でファイルがない」状態でも、「仕様変更で列名を追加した」場合でも、設定ファイルに記載しておけば、勝手に列名が追加されるので安心です。

# 終わりに

いかがでしたでしょうか？実装の参考になれば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
LAMP環境の構築 Part1

Linuxサーバ構築の学習において、LAMP環境の構築を行った。
今回は、LinuxとApachの設定を行い、Webページを表示させるところまでを試してみた。


【Linuxの設定】
リポジトリを追加することで、最新のソフトをyumでインストールできるようになる。
リポジトリ→ソフトウェアが格納されているデータベースのようなもの。
EPELリポジトリ→Red Hat Enterprise Linux(RHEL)向けの追加パッケージ。
Remiリポジトリ→mysqlやPHPの新しいバージョンなどを集めているリポジトリ。

sudo yum update→インストールされているソフトウェアのアップデート

sudo yum install epel-release→epelリポジトリのインストール

sudo yum install 参照するURL→remiリポジトリのインストールでは、「remi repository」の公式サイトから参照するURLをコピーして貼り付ける。

yum repolist→有効なリポジトリの確認

less /etc/yum.repos.d/対象のリポジトリ名→リポジトリを無効にしたい場合は、enabled-1の部分をenabled-0に変更する。

sudo yum install httpd→Apachのインストール

httpd -v→Apachのバージョン確認

sudo systemctl enable httpd→OSを再起動した際、Apachが自動的に起動されるように設定

systemctl status httpd→現在のApachの状態を確認

ファイアーフォールの設定
sudo firewall-cmd --permanent --zone=public --add-service=http→httpの通信を許可

sudo firewall-cmd --permanent --zone=public --add-service=https→httpsの通信を許可

sudo firewall-cmd --reload→ファイアーフォールのリロード

SELINUXの設定
getenforce→selinuxの確認

sudo vi /etc/selinux/config→selinuxの編集。無効化したい場合は、SELINUX=disabledに変更する。

静的なwebページの表示
WebサーバのトップとなるDocumentRootにhtmlファイルを置くことで表示することができる。

less /etc/httpd/conf/httpd.conf→Apachの設定ファイルでDocumentRootのパスを確認する。

sudo vi DocumentRootのパス/index.html→表示させたい文字を入力し、ファイルを保存して閉じる。

ブラウザに仮想マシンのipアドレスを入力することで、Webページに先ほどの文字を表示させることができる。
DockerでFlask+MySQLを動かしたときのAccess deniedエラー

# はじめに
DockerでFlaskとMySQLのコンテナを立てて、FlaskからMySQLに接続しようとするとFlaskがエラーを吐いて落ちてしまう状況に何度か遭遇した。対処方法として万人に有効かは分からないが、一応記録する。

# 出たエラー
```
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
```

# 解決方法
MySQLにマウントしているディレクトリを一旦消してからコンテナを立て直す。

# 解説
このエラーが出る原因のひとつは、MySQLの設定を変えてからコンテナを立て直したことである。自分の場合は、環境変数のMYSQL_ROOT_PASSWORDを別のものに書き換えたことが原因だった。
MySQLコンテナが初めて立ち上がる際には、MySQLサーバーの設定ファイル群が自動で作られる。これらは永続ボリュームに保存される。そのため、MySQLの設定を変えた場合は、設定ファイル群を作り直す必要があったのだ。
しかし、一度コンテナを立てると、設定を変えても作り直されることはないため、上記のようなエラーが出ることになる。なので、解決方法としてはボリュームの中身を削除するか、MySQLサーバーに入って設定をいじるということになる。
環境構築の段階で起きやすいエラーなので、作り直してしまった方が早そうである。

# まとめ
コンテナ上のMySQLサーバーの設定を変更した場合は、コンテナだけでなくデータベースのディレクトリを作り直さないとエラーが出る場合がある。
mysql 5.7の使い方

#### 随時更新します

## ユーザの作成と、どこからでもアクセスできる権限

例）examユーザでパスワードがpass

```
create user 'exam'@'%' identified by 'pass';
```

例）examユーザはどこからでもアクセス可能

```
grant all privileges on *.* to 'exam'@'%';
```
擬似逆行列

ムーア-ペンローズの擬似逆行列と，冗長な自由度を持つ連立方程式の解法についてまとめる．

行列$A\in \mathbb{R}^{m\times n}$が存在する．
$A$に対して，以下の性質を満たす行列$X$を考える．

1. $AXA = A$
2. $XAX = X$
3. $(AX)^T = AX$
4. $(XA)^T = XA$

このような$X$のことを$A$の（ムーア-ペンローズの）**擬似逆行列**といい，$A^\dagger$（ダガー）あるいは$A^+$と表す．

# 擬似逆行列を作る

$A$の階数が$r$であるとき，行列の基本変形によって

```math
    PAQ = \begin{bmatrix}
    I_r & O_{r,n-r}\\
    O_{m-r, r}&O_{m-r,n-r}
    \end{bmatrix}
    =\begin{bmatrix}
    I_r\\
    O_{m-r, r}
    \end{bmatrix}
    \begin{bmatrix}
    I_r & O_{r,n-r}
    \end{bmatrix}
```

となる．ここで，$I_r$は$r \times r$の単位行列，$O_{kl}$は$k \times l$のゼロ行列を表す．
ここで，

```math
    B=P^{-1}\begin{bmatrix}
    I_r\\
    O_{m-r, r}
    \end{bmatrix},\\
    C=\begin{bmatrix}
    I_r & O_{r,n-r}
    \end{bmatrix}Q^{-1}
```

とおくと，
$$
    A=BC
$$
が成立する．この$B$と$C$を用いて
$$
D = C^T(B^TAC^T)^{-1}B^T = C^T(B^TBCC^T)^{-1}B^T
$$
とおくと，$X=D$となる．

(証明)
まず，$B^TB$と$CC^T$は正則である（証明略）．このとき，
$$
    ADA = BC\{C^T(CC^T)^{-1}(B^TB)^{-1}B^T\}BC\\
    =B(CC^T)(CC^T)^{-1}(B^TB)^{-1}(B^TB)C\\
    =BC =A
$$
$$
    DAD = \{C^T(CC^T)^{-1}(B^TB)^{-1}B^T\}BC\{C^T(CC^T)^{-1}(B^TB)^{-1}B^T\}\\
    =C^T(CC^T)^{-1}(B^TB)^{-1}(B^TB)(CC^T)(CC^T)^{-1}(B^TB)^{-1}B^T\\
    =C^T(CC^T)^{-1}(B^TB)^{-1}B^T = X
$$
が成立する．また，
$$
    (AD)^T = \{BC(C^T(CC^T)^{-1}(B^TB)^{-1}B^T)\}^T\\
    = \{B(B^T B)^{-1}B^T\}^T \\
    = (B^T)^T\{(B^TB)^T\}^{-1}B\\
    = B(BB^T)B^T = AD
$$
である．$(DA)^T=DA$についても同様．
したがって，$X=D$である．

## 擬似逆行列の一意性

擬似逆行列は一意で，
$$
A^{\dagger} = C^T(B^TBCC^T)^{-1}B^T
$$
のみである．

（証明）
$X$も$Y$も擬似逆行列であると仮定すると，$X=Y$が導かれる．

# 線形連立方程式を解く

線形連立方程式
$$
    A\boldsymbol{ x} = \boldsymbol{b}
$$
を解く．$A \in \mathbb{R}^{m\times n}$, $\boldsymbol{x}\in \mathbb{R}^n$, $\boldsymbol{b}\in \mathbb{R}^m$である．

## 正則な場合

$m=n$で，$A$が正則であれば$A^{-1}$が存在するため，
$$
    \boldsymbol{x} = A^{-1}\boldsymbol{b}
$$
が直ちに得られる．これは，線形連立方程式において未知数の数と式の数が一致している場合である．解は一意になる．

## 正則でない場合

もっと一般的な問題を考えよう．すなわち，未知数と式の数が一致しない場合，$A$は正則ではない．さらに場合分けをするなら，未知数に対して式が足りない場合($m<n$)と，未知数に対して式が多すぎる場合($n<m$)が存在する．

* 前者は，拘束条件が少ないため，無数に解を持つことができる．
* 後者は，拘束条件が多すぎるため，解が存在しない．

いずれの場合においても，解は$||A\boldsymbol{x}-\boldsymbol{b}||$を最小化するように探索する．前者では，原点から最も近い解を一つ選択することになる．後者では，最も近くまで近づけるものを解として扱うことになる．

拘束条件が少ない場合，ラグランジュの未定乗数法によって
$$
\boldsymbol{x} = A^{\dagger}\boldsymbol{b} + (I_n-A^{\dagger}A)\boldsymbol{k}
$$
を得る．$\boldsymbol{k}\in\mathbb{R}^n$は任意のベクトルであり，解が無数に存在することを表す．

拘束条件が多すぎる場合，(二乗誤差の偏導関数)$=0$を解くことによって，
$$
\boldsymbol{x}^* = (A^TA)^{-1}A^T\boldsymbol{b}
$$
を得る．ただし，これは最適化の結果でしかなく，いかなる方程式の解でもないことに注意する必要がある．

## 例題

例えば冗長な自由度を持つロボットアームの逆運動学問題を考えてみよう．このとき，手先速度$\boldsymbol{v}$はヤコビ行列$J$と関節速度$\dot{\boldsymbol{q}}$を用いて
$$
    \boldsymbol{v} = J\dot{\boldsymbol{q}}
$$
で与えられる．$\boldsymbol{v}\in \mathbb{R}^6$であるのに対し，冗長自由度アームでは$\dot{\boldsymbol{q}}\in \mathbb{R}^n$ $n>6$である．このような場合，任意の手先速度は様々な関節角度の組み合わせによって得られる．すなわち，
$$
    \dot{\boldsymbol{q}} = J^\dagger\boldsymbol{v} + (I_n - J^\dagger J)\boldsymbol{k}
$$
となり，$\boldsymbol{k}$が任意性を表す．

逆に，自由度に対して制御系が不足している劣駆動システムの場合，入力の制約から任意の出力を達成することは不可能である．

# 参考文献

斎藤正彦，「線形代数演習」，東京大学出版会，1985．
吉川恒夫，「ロボット制御基礎論」，コロナ社，1988．
パスワードでのGit操作を禁止　トークン認証手順


##■背景
いつも通りに、git操作を行っていると、突然push時に、下記エラーが出力されました。
clone,pullなどもできない！！？

```
remote: Password authentication is temporarily disabled as part of a brownout. Please use a personal access token instead.
remote: Please see https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations/ for more information.
fatal: unable to access 'https://github.com/repository.git/': The requested URL returned error: 403
```
そのため、調査してみました。
#####GitHub、2021年8月13日以降パスワードでのGit操作を禁止
(https://news.mynavi.jp/article/20201222-1604003/)
の記事を発見しました。
##■原因
これまでローカルでリモート(github)にアクセスするためにはパスワード認証で問題ありませんでした。
しかし、__脆弱性防止のために個人アクセストークン認証に変更__になるみたいです。(2021年8月13日にパスワード認証廃止)

さらに、詳細を確認すると、
####
__下記の期間は一時的にパスワード認証が停止__され、パスワードを使ったGit操作ができなくなる。
エラーが出たのは2021年7月28日18時頃だったので、下記が原因かと思います。

- 2021年6月30日 UTC 7時から10時（日本時間 同16時から19時）
- 2021年6月30日 UTC 16時から19時（日本時間 7月1日1時から4時）
- 2021年7月28日 UTC 7時から10時（日本時間 同16時から19時）
- 2021年7月28日 UTC 16時から19時（日本時間 7月19日1時から4時）

##■パスワード認証からトークン認証に変更
2021年8月13日以降パスワードでのGit操作を禁止になるため、早々にトークン認証に切り替えたので、方法を記載します。


###1. キーチェーンアクセスを開き、gitを検索し、インターネットパスワードを削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/a1aec6b4-b0ef-b02c-a81b-63c7ec652c92.png)

![スクリーンショット 2021-07-28 23.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/e1c756c1-e7d3-6a38-6586-3028975dbcbb.png)

###2.トークンの生成を行う。
githubにログインし、setting→Developer Setting→Personal access tokens→Generate New Token
をクリックし、Note(タイトル)、Expiration、repoにチェックを入れてトークンを生成します。
※トークンが表示されるので、保管しておきましょう。
![スクリーンショット 2021-07-29 0.18.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/a1c714b8-2f90-bf61-43a5-e0270b5d6ebe.png)

###3. トークン認証を設定する
下記、でトークンを設定しましょう。
###■パターン１

```
git remote set-url origin https://{トークン名}@github.com/{リポジトリ名}.git
```
　リポジトリ名などを間違えてしまうと、下記のようにエラーが出力されます。

```
remote: Not Found
fatal: repository 'https://github.com/リポジトリ名.git/' not found
```
トークン認証を設定後、下記、コマンドでリモートのリポジトリと一致しているか確認してみましょう。

```
git remote -v
```
###■パターン２
上記は、直接トークンを設定しています。毎回パスワードを求められずに操作できるので便利ですが、セキュリティ的に問題がある場合があります。
なので、
トークンを設定せずに、毎回入力を求められるように設定します。

```
vim .git/config
```
まず、gitの設定ファイルをvimモードで開きます。
そして、下記の　urlをユーザー名のみに設定します。

```
[remote "origin"]
        url = https://ユーザー名@github.com/リポジトリ名.git
        fetch = +refs/heads/*:refs/remotes/origin/*
```
すると、
リモート操作時は、パスワードが求められるので、トークンを入力しましょう。

##■最後に
既に、パスワード認証中にgit cloneしてきたものは、上記の手順でgit操作が可能になりますが、
トークン認証後にgit cloneしてきたものは、上記の設定は不要になります。

以上、最後まで閲覧頂きありがとうございます。
sshの鍵作成 ed25519



- 最近強いと言われているed25519の鍵を作る。
- Enter passphreseのところでパスワードを設定する。sshするときにパスワード聞かれるのが嫌な人はそのままEnterでOK

- 作成すると自分のhomeディレクトリの下にsshの鍵が生成される。
    - .pubとなっているのが公開鍵
    - なにもついていないのが秘密鍵

- よく秘密鍵を送ってきてサーバに登録してくださいという人いるけど、公開鍵は公開してもいいけど、秘密鍵は自分だけの秘密にして置いてください。
    - 秘密鍵を公開すると後悔します。
- 


```
pupupupupu@devPC dev % ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/pupupupupu/.ssh/id_ed25519): 
Created directory '/Users/pupupupupu/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/pupupupupu/.ssh/id_ed25519.
Your public key has been saved in /Users/pupupupupu/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:GmuekgaxWW3tfjpGBu6ev1riCvI6xPfxvC3yETsxAQI pupupupupu@devPC.local
The key's randomart image is:
+--[ED25519 256]--+
| E.. .           |
|    . .          |
|     . o         |
|  . . + o        |
|.  = o.*S        |
| o+. ..+O        |
|o o..oOB.        |
|.o .+*.OB .      |
|.o...+X***       |
+----[SHA256]-----+
hoge@devPC dev % ls ~/.ssh/id_ed25519
/Users/pupupupupu/.ssh/id_ed25519
pupupupupu@devPC dev % ls ~/.ssh/id_ed25519.pub 
/Users/pupupupupu/.ssh/id_ed25519.pub
pupupupupu@devPC dev % ls -la ~/.ssh/          
total 16
drwx------   4 pupupupupu  staff  128  7 29 19:14 .
drwxr-xr-x+ 18 pupupupupu  staff  576  7 29 19:14 ..
-rw-------   1 pupupupupu  staff  464  7 29 19:14 id_ed25519
-rw-r--r--   1 pupupupupu  staff  100  7 29 19:14 id_ed25519.pub
pupupupupu@devPC dev % 
```
【Unity】動的生成されるGameObjectにInjectする方法

# 概要
疎結合なクラス設計で開発する際に非常に便利なZenject/Extenjectですが、
扱いの難しさ故に、ちょっとしたことでハマってしまいます。

今回は、動的に生成されたGameObjectがInjectされない問題とその解決策を記載していきます。
# Prefabを動的生成する
以下のようなPrefabがあります(以下「プレイヤーPrefab」と表記)。
![ZenAuto01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081029/e0cc6c60-e8ec-6234-4143-b229ee2ccbbe.png)

プレイヤーPrefabにはPlayer.csがアタッチされています。

```Player.cs
// ゲームステータスを管理するマネージャ
[Inject] GameManager manager;

void Start()
{
    // ゲームステータスがGOなら処理を行う
    if(manager.GetGameState == "GO"){
        // 好きな処理を書く
    }
}
```

そしてScene内には位置情報だけのPlayerSpawnerオブジェクトがあり、PlayerSpawner.csがアタッチされています。
![ZenAuto02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081029/f82979a4-ba10-d818-d715-61c8c5bc0003.png)

プレイヤーPrefabはHierarchyには設置せず、PlayerSpawner.csによって動的生成される仕様とします。

```PlayerSpawner.cs
[SerializeField] GameObject playerPrefab;

void Start()
{
    // プレイヤーPrefabを動的生成する
    Instantiate(playerPrefab, new Vector3(0, 0, 0), Quaternion.identity);
}
```

以上の条件で実行してみると、Player.csにNullReferenceExceptionのエラーが出ます。

エラーの原因はアタッチ先のプレイヤーPrefabが、PlayerSpawnerから動的生成されたことによりInjectされず、managerがnullになってしまうからですね。
# 解決策
とても簡単で、ZenAutoInjectorをプレイヤーPrefabにアタッチすればOKです。
![ZenAuto03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081029/7b04907e-6a21-8f38-8b76-bc6a4cdce7a3.png)

DI Containerを直接使用し、InstantiatePrefabを行うことでも解決できますが、無駄にコードを増やさずに済むのでZenAutoInjectorを使用するのがおすすめです。
【Automation Anywhere】FirefoxとAutomation 360

Automation Anywhere の最新版、Automation 360はChromeで使うものというイメージが強いかもしれませんが、Firefoxとの互換性もあります。

# Control Roomや開発画面をFirefoxで開く場合

特別な設定は不要で、普通にFirefoxでControl Roomにアクセスして開くだけです。
開発画面も普通に動きます。

# Firefox で開いたWebサイトをレコーダーでつかみたい場合

Firefox用のアドオンを追加する必要があります。
アドオンの追加の仕方は以下のとおりです。

## Firefox用アドオンの追加方法

### Step1：右上のメニューから「アドオンとテーマ」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/29339fa5-3a9d-c36f-9f7b-6cb1882eac8b.png)

### Step2：「アドオンを探す」に「automation」と入力し検索します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/070665f4-dfb2-8ef9-0daa-db09667e6938.png)

### Step3：検索結果の中から「Automation 360」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/7be79653-deb6-5161-9f94-10d55336d8ce.png)

### Step4：「Firefoxへ追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/6cc1cb12-b75a-1bfb-742e-cdd917c0b6a1.png)

### Step5：確認のポップアップが出てくるので、「追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/92bfca52-eb2d-978c-96c7-0336826b22c7.png)

### Step6：完了のポップアップが出てくるので、「OK」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/1c7c9b46-d83a-df13-cfc3-6dcd22a75555.png)

#以上！

以上の手順で、FirefoxユーザーのみなさんもAutomation 360の開発・利用を始められます！

Enjoy！！
【侵入防御ルール@解説】1010564 - Joomla Arbitrary File Upload Vulnerability (CVE-2020-23972)【CVE-2020-23972】

機能種別：侵入防御機能
ルール種別：侵入防御ルール、DPIルール


■ルール名
 1010564 - Joomla Arbitrary File Upload Vulnerability (CVE-2020-23972)

■ルールの説明

攻撃者はアプリケーションに認証せずにアプリケーションのアップロード機能にアクセスし、ファイルも起因してアップロードできる また 2倍の拡張 内部形式と名前ファイルを変更することによってバイパスされうる無制限のファイルアップロードの問題 。

翻訳微妙なんで原文記載
An attacker can access the upload function of the application without authenticating to the application and also can upload files due the issues of unrestricted file uploads which can be bypassed by changing the content-type and name file too double extensions.


■脆弱性
(主な脆弱性対象(他にもありますが詳細はリンク参照))
Joomlaコンポーネント
GMapFPバージョンJ3.5とJ3.5free

 
(ソース)
https://www.tenable.com/cve/CVE-2020-23972


【CVE番号】 
CVE-2020-23972

 

■ルールにて設定できること。
無し


■推奨設定の検索対象か否か
対応
 

【芋的見解】
CMSなんで、Joomla使ってる環境かつ、対象のバージョンを使用している場合、
根本対処として、アップデートすることをおすすめします。
アカウントや権限に関する脆弱性ではないので、漏洩等のリスクは無いですが、
ディスクを枯渇させることもでき最悪SSHできないとか自体に陥ったりすると面倒なことになるかと。
Prism Template Packのコードスニペットが表示されない

## 背景

WPFアプリケーションのフレームワークとして[Prism](https://prismlibrary.com/)がOSSにて開発されている。
Prismアプリケーションを開発するためのVisualStudio向け拡張機能が[Prism Template Pack](https://marketplace.visualstudio.com/items?itemName=BrianLagunas.PrismTemplatePack)として提供されている。

## 問題

Template Packをインストールしても、スニペットだけがVisualStudioに存在しない場合がある。

## 解決法

Template Packの[issue](https://github.com/PrismLibrary/Prism/issues/330)に[解決策](https://github.com/PrismLibrary/Prism/issues/330#issuecomment-462186507)が載っていた。

> Remove the wrong folder and "ADD" the folder from as described by Brian
C:\Users{UserName}\AppData\Local\Microsoft\VisualStudio(Version of VS)\Extensions{Install ID}\Snippets\CSharp\Prism

- もし、2つ以上あるいは不適切なディレクトリーのスニペットが登録されていたら削除する。
- `C:\Users\{UserName}\AppData\Local\Microsoft\VisualStudio\(ランダムなID)\Extensions\{ランダムなID}\Snippets\CSharp\Prism` のフォルダーをコードスニペットマネージャーにおいて登録する。

### 補足

コードスニペットマネージャーは、`Ctrl+K, Ctrl+B`で出すか、`ツール→コードスニペットマネージャー`の順で出せる。

![スクリーンショット 2021-07-29 184224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284167/621756ce-1f5b-fc4e-f8b3-941413fea80b.png)


## 考えられる原因

VisualStudio 2019のCommunity版とEnterprise版をインストールしたりしたから、Template Packをインストールしたときに正しいディレクトリをスニペットマネージャーに登録出来なかったからではないかと考えられる。
ヒプマイ楽曲で1番多くでてくる言葉を調べてみた　一二三編

##はじめに
はじめまして。立夏と申します。
この間ヒプマイというコンテンツの番組の中で『楽曲に1番多く出てくる言葉は何か』を当てるコーナーがありました。
私はちょうどプログラミングの勉強中で「これって形態素解析を使って求めたのでは？？」と思い練習として私もやってみました。初心者故至らぬ点が多いと思いますが暖かく見守っていただければ幸いです。


##目的
伊弉冉一二三の楽曲に1番多く使われている言葉を調べる


##準備
〈環境〉
Calaboratory

〈使用言語〉
python

まずは形態素分析をしてくれる**Tokenizerをインストール**します

```python:
!pip install Janome==0.3.7
```

仕様が変わっているので今回は旧バージョンで進めていきます

▼必要な**モジュールをインポート**しておきます

```python:
import glob
from janome.tokenizer import Tokenizer
from collections import Counter
```



▼歌詞について
スクレイピングは歌詞だとできないかもということと担当パートを判断し抜き出すことは不可能だと思いソロ曲と全員曲の一二三の担当パートの歌詞をまとめたテキストを用意しました
今回は10曲を対象にしています
（初心者故ここはアナログの方が早いと判断しましたがもっといい方法があったのかも…）

##分析開始

▼**単語を取り出すための関数を設定**します
ヨコハマのときと同じで名詞、動詞、形容詞、形容動詞に限定しています
歌詞内の！や（）も名詞として取り出していたのでそれらを除くコードと英語の大文字を小文字に直すコードを足しました

```python:
# 品詞を取り出し「名詞、動詞、形容詞、形容動詞」のリスト作成
def tokenize(part):
    part = part.lower()
    t = Tokenizer()
    tokens = t.tokenize(part)
    words = []
    for token in tokens:
        part_of_speech = token.part_of_speech.split(",")[0]
        if part_of_speech in ["名詞", "動詞", "形容詞", "形容動詞"]and not token.surface in ["!", "!!", "(", ")", "'", "?"] :
          words.append(token.surface)
    return words
```

▼歌詞を書いた**テキストを読み込み**先程の関数に適用します

```python:
f = open("/content/drive/MyDrive/hihumi.txt", "r", encoding="utf-8")
song = f.read()
song = tokenize(song)
```

これで単語を取り出せました
['oh', 'yeah', '持っ', 'こい', 'シャンパン', '終わら', 'party'・・]というようなリストになっています

▼それぞれの**単語数を数え出力**します

```python:
#単語の出現回数をカウント
counts = Counter(song)
sorted(counts,key=counts.get,reverse=True)

print(counts)
```

##結果
上のコードを実行すると
{'シャンパン': 28, '僕': 21, '終わら': 14, 'party': 14, '朝': 13, 'グイ': 10, 'こい': 9, '円': 9, 'さ': 9,・・  

このような結果が出ました（長いので載せるのは途中までにしています）
「さ」が気になりますが概ねちゃんとした結果が出ていると思います
##まとめ
今回の結果上位をまとめると

**１位　シャンパン　28回**
**２位　僕　　　　　21回**
**３位　終わら　　　14回**
**３位　party　　　 14回**
**４位　朝　　　　　13回**

となりました
やはりシャンパンが1位ですね！ファンの方は予想通りだったのではないでしょうか？
複数曲で出てきている分ナゴヤの『伽』32回を越せるかと思っていましたが…空却くん強し
今後もたくさんシャンパンコールして欲しいですね

##最後に
今回は１つのテキストを対象にしているので多少荒いコードになっていますが
他のキャラでも試すときは関数設定や特定の語句の削除などの部分を整えようと思います。
では、今回はここまで！閲覧ありがとうございました。