OmniAICreator/Qiita-1.07M huggingface dataset:
aws S3 + CloudFront + Certificate Manager + Route53 で静的Webページを配信する

# 最終形

![AWS Networking (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/7dd96364-8ca7-0d19-231a-5ab05f10f168.png)


# これからやってみること

S3 + CloudFront + Route53 の組み合わせで静的 Webページ を配信するのは、aws のベストプラクティスの中でも「横綱」と言われています。私個人の Webページ をこのスタイルで配信してみましたので、その手順をご紹介します。

# 何がうれしいのか

- S3 と CloudFront はともに極めて高い可用性を持つサービスであるため、安心してWebページの配信を任せられる
- すべてマネージドサービスなので運用、保守はすべて aws で対応してもらえる
- Certificate Manager により面倒な SSL/TLS証明書 の取得と更新を自動で対応してもらえる
- 個人の Webページ であれば月額数十円で運用できる

# 前提条件

- S3、CloudFront の操作が可能な aws アカウントを所持している
- 独自ドメインを所持し Route53 などの「権威DNS」でホストしている

話は少しズレますが、私は以前 (2017年)、レンタルサーバからWebページを配信しておりまして、DNS　もレンタルサーバの機能を使っていました。当時はこの DNS を用いて S3 + CloudFront によるWeb配信にチャレンジしたのですが、レンタルサーバの機能では必要な設定ができませんでした (S3 をエンドポイントにするところまでは対応可能だったが Certificate Manager の設定で必要な DNS 検証ができなかった)。

そこでレンタルサーバ運営会社で取得したドメインを aws へ移管し、Route53 によるDNS管理をはじめるようになりました。

Route53 はいわゆる「権威DNS」なのでドメイン管理で必要な設定はすべて実施できます。SLA は１００％と言われており、繰り返し起こるドメイン乗っ取りの恐怖から解放され、しかも月額 0.5USD ほどで運用できてしまうので、aws らしい、とても高価値なサービスだと思っています。

# 公式手順

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudfront-serve-static-website/

この公式手順の中にある「OAIによってアクセスが制限されているオリジンとして REST API エンドポイントを使用する」方式で実装を進めました。つまり、S3 のパブリックアクセスを行うことなく CloudFront に対してのみアクセスを可能とする、とてもセキュアなデータアクセス方式を採用しています。 

# 動作確認

代替ドメイン名 (tms.demoru.net) で Webページが表示できれば OK

https://tms.demoru.net だけでなく、http://tms.demoru.net でアクセスすると https://tms.demoru.net にリダイレクトされるので確認しておきましょう。

# 成果物

[tms.demoru.net](https://tms.demoru.net)

# 組織

[unremoted.com](https://enremoted.com)

# おまけ　ドメインが expired したらどうなるのか

今回 tmstmp.com で配信していたページを tms.demoru.net に移したのは tmstmp.com が 2022年2月15日でドメインの有効期限を迎えるので、このドメインを打ち切りにしようとしたためでした。

さて、com ドメインが expired したらどうなるのか？

aws からはメールで以下の「重要な日付」が通知されています。

```
2022年2月15日：ドメインは一時停止され、インターネットで利用できなくなります
2022年2月15日-2022年3月30日：標準料金で登録を更新できます。
2022年3月31日：ドメインがシステムから削除されます。
2022年3月31日-2022年4月30日：ドメインの登録を復元できます。ドメイン登録を復元するための価格は、トップレベルドメイン（TLD）によって異なります。詳細については、AWSRoute53の料金をご覧ください。
2022年5月5日：レジストリによっては、この日付以降、誰でもこのドメインを登録できる場合があります。
```

なかなか経験できないイベントなので、どのタイミングで利用できなくなるのか確認してみました。事前の予想は、国際標準時の 2/16 0:00 または太平洋時の 2/16 0:00 以降に expires すると考えていました。日本時間で言うと 2/16 9:00 または 2/16 17:00 以降ということになります。

結果は、2/16 の 23時過ぎにブラウザからの閲覧ができなくなりました。aws より 23:04 に「Registration for tmstmp.com has expired」というメールが来ていましたので、このタイミングで expires したものと思われます。このメールにはドメインの利用を継続するためのリンクと、カスタマーサポートへ問い合わせるためのリンクが添付されていました。

あらためて、ありがとう、さようなら tmstmp.com

さくらインターネットのレンタルサーバでホームページ配信やメールサービスを行ったり、aws へ移管後は S3 からのホームページ配信や、SES を用いたメール配信、EC2 を用いたサービスの ELBエンドポイントをポイントしたり、Google Workspace の独自ドメイン利用、各種証明書の取得や更新のための DNS 検証など様々なシーンで役に立ってくれました。

Route53 のホストゾーンと、CloudFront のディストリビューション、静的ページを配置していたバケットは削除しておきます。
MATLABで数字をExcelの列名に変換

2/25 関数変更
# はじめに
ある日, こんな質問が来ました.

「MATLABで列番号をExcelの英表記に変換することってできますか？」

ということで, MATLAB Documentationの検索タイムが始まりました. 私もExcelスプレッドシートからデータをMATLABにインポートしたことは幾度となくありましたので, その周辺のDocumentationを探していたのですが, 見つかりませんでした. そこで, 「そうだ自分で作ろう！！」となりました.

この記事では, **MATLAB R2021b**を使用しております.
また, 本記事で示されたコードは, **今回示した問題以外での検証等は行っておりません**.

# 基本的な指針
Excelの列名はアルファベットによって表されます. つまり, **列名は10進法ではなく26進法**であらわされます. MATLABには, 10進数整数を$n$進数表現に変換する便利な関数, [dec2base](https://jp.mathworks.com/help/matlab/ref/dec2base.html)が用意されています. そして, 得られたchar配列の各文字をASCIIコード表に基づいて, 以下のように変換します.

| 変換前 文字 | 変換前 10進数 | 変換後 文字 | 変換後 10進数 |
| :----: | :----: | :----: | :----: |
|  '0'  |  48  |  'A'  |  65  |
|  '1'  |  49  |  'B'  |  66  |
|  '2'  |  50  |  'C'  |  67  |
|  '3'  |  51  |  'D'  |  68  |
|  '4'  |  52  |  'E'  |  69  |
|  '5'  |  53  |  'F'  |  70  |
|  '6'  |  54  |  'G'  |  71  |
|  '7'  |  55  |  'H'  |  72  |
|  '8'  |  56  |  'I'  |  73  |
|  '9'  |  57  |  'J'  |  74  |
|  'A'  |  65  |  'K'  |  75  |
|  'B'  |  66  |  'L'  |  76  |
|  'C'  |  67  |  'M'  |  77  |
|  'D'  |  68  |  'N'  |  78  |
|  'E'  |  69  |  'O'  |  79  |
|  'F'  |  70  |  'P'  |  80  |
|  'G'  |  71  |  'Q'  |  81  |
|  'H'  |  72  |  'R'  |  82  |
|  'I'  |  73  |  'S'  |  83  |
|  'J'  |  74  |  'T'  |  84  |
|  'K'  |  75  |  'U'  |  85  |
|  'L'  |  76  |  'V'  |  86  |
|  'M'  |  77  |  'W'  |  87  |
|  'N'  |  78  |  'X'  |  88  |
|  'O'  |  79  |  'Y'  |  89  |
|  'P'  |  80  |  'Z'  |  90  |

この表によれば, 数字には17を加え, アルファベットには10を加えればよいことがわかります. ただし, 以下の二つに注意することが必要です.

* 10の位以上の文字は0ではなく1から始まるため, 1を差し引いてから変換を行う必要がある.
* MATLABの配列はインデックスが1から始まるため, 変換前に1を引く必要がある.

# 作成した関数 excel_column
以上に注意すると以下のような関数が作成される.

```code:matlab
function answer = excel_column(num_column)

%
% excel_column - Convert Interger to the string equivalent to Excel column
%
%   string = excel_column(num_column)
%   
%   -Inputs-
%   num_column  - Scalar Integer Number
%   
%   -Outputs-
%   string      - Excel Column Name String
%
%   --- Usage Example ---
%   
%   number = randi(100)
%   letter = excel_column(number)
%
%   ---------------------
%
%

if (isscalar(num_column))
    answer = dec2base(round(abs(num_column))-1,26);
    for ii=1:length(answer)
        if (ii ~= length(answer))
            answer(ii) = answer(ii) - 1;
        end
        if (answer(ii) > 63)
            answer(ii) = answer(ii) + 10;
        elseif (answer(ii) > 47)
            answer(ii) = answer(ii) + 17;
        end
    end
    answer = string(compose(answer));
else
    error('Sorry!! This function can get only scalar.');
end
end
```
この関数は引数としてスカラー値を受け取り, そのスカラー値に相当するExcelの列名が出力されます.

# 確認

```code:matlab
clear all; close all; clc;
%% Convert Number to Alphabet following Excel Spread sheet
n = 5; max_n = 50;
number = randi(max_n,1,n);
letter = string(zeros(1,n));
for ii=1:n
    letter(1,ii) = excel_column(number(ii));
end

number
letter
```

```text:result
>> number =

     5    14    28    48    49


>> letter = 

  1×5 の string 配列

    "E"    "N"    "AB"    "AV"    "AW"
```
なんとなくうまくいってそう..

# おわりに
本アイデアをくれた質問者の方に, 感謝申し上げます.
[py2rb] 多重継承の５

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# 多重継承 (Python)
https://qiita.com/superrino130/items/baafa3d35870e63cd5bf#comment-4d89a0f12472ee16fec8

前回の記事の [コメント](https://qiita.com/superrino130/items/baafa3d35870e63cd5bf#comment-4d89a0f12472ee16fec8) にて、@Nabetani さんよりメソッドのまとめ方を教えていただきましたので、それを踏まえて再びやってみました。

![20220224a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/45899ae7-6363-8b1e-246e-741e977e44ed.png)

+ 一番目の行は、ファイル名（Rubyですとmodule名）
+ C:class, SC:継承するsuperclass
+ D:メソッド定義, DS:メソッド内でsuperを使用しているメソッド定義

# 継承テスト(Python)
```python
class C5:
    s1 = None
    s3 = None
    s5 = 's5'
    def __init__(self):
        print('C5')

class C4(C5):
    s4 = 's4'
    def __init__(self):
        print('C4')
        
class C2(C4):
    s2 = 's2'
    def __init__(self):
        print('C2')
        super().__init__()

class C3:
    s3 = 's3'
    def __init__(self):
        print('C3')

class C1(C2, C3):
    s1 = 's1'
    def __init__(self):
        print('C1')
        super().__init__()
        print(self.s1)
        print(self.s2)
        print(self.s3)
        print(self.s4)
        print(self.s5)

C1()

# output
C1
C2  
C4  
s1  
s2  
None
s4  
s5 
```
ふむふむ。
クラス変数も受け継がれてますね。
# 継承テスト(Ruby)
```ruby
module C5
  @@s1 = 'None'
  @@s3 = 'None'
  @@s5 = 's5'
  def __init__
    puts 'C5'
  end
end

module C4
  include C5
  @@s4 = 's4'
  def __init__
    puts 'C4'
  end
end
      
module C2
  include C4
  @@s2 = 's2'
  def __init__
    puts 'C2'
    super
  end
end

module C3
  @@s3 = 's3'
  def __init__
    puts 'C3'
  end
end

class C1
  include C2, C3
  @@s1 = 's1'

  def initialize
    __init__
  end

  def __init__
    puts 'C1'
    super
    puts @@s1
    puts @@s2
    puts @@s3
    puts @@s4
    puts @@s5
  end
end

c = C1.new
p C1.ancestors

# output
C1
C2
C4
s1
s2
s3
s4
s5
[C1, C2, C4, C5, C3, Object, Kernel, BasicObject]
```
`s3`が惜しかったですが、継承チェーンは正しいようです。
# メモ
+ Python の 多重継承の５ を学習した
+ 百里を行く者は九十里を半ばとす
オブジェクト詰め替え対策の一つ -- interface利用(golang)

ORM層とdomain層とデータ受け渡しをする場合、オブジェクト詰め替えが頻繁に発生することで、以下のデメリット・不便が感じている：

- コーディング作業がめんどくさい
- 詰め替え漏れ故のバグ
- 詰め替え処理自体の処理コストはどうかとの心配


これで試した対策の一つは interface利用のことです。
詳細はあとで...
【Excelアドイン】SharperlightでExcelレポートを作ってみる

記事：[Sharperlightをお手持ちのデータベースに繋ぐ](https://qiita.com/Miki_Yokohata/items/f7973bbc0e9fc65a7416)で作成し保存したクエリを使用して、Excelレポートの作成をしてみます。
## Sharperlight Excelアドインの設定
Sharperlightアップリケーションメニューから「Excelアドインをインストール」を選択します。
![Qiita 2022-02-24 Figure 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/aa84b77a-b3c6-cc7b-fd38-f936240d7cf3.png)
Excelを終了してくださいというメッセージが表示されるので、OKをクリックします。
![Qiita 2022-02-24 Figure 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ef1e88c8-c17f-20d1-9c65-7bd81967fafc.png)
その後、Windowsのユーザーアカウントコントロールが表示されるので、Yes(はい)をクリックします。
背景で処理が行われ数秒で終了します。
## Excelレポートの作成
Microsoft Excelを起動し、Sharperlightメニューおよびリボンがあることを確認します。
(Excelが英語版ですいません。:bow_tone1:)
![Qiita 2022-02-24 Figure 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1c4a2827-3479-8507-7a74-a779e002f046.png)
では、始めましょう。セルC5に移動します。ここにSharperlightの数式を配置します。アンカーセルといいます。
”帳表”ということでSharperlightリボンの”数式”グループから”テーブル”を選択します。
![Qiita 2022-02-24 Figure 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/89d05378-132a-0919-64a4-81049fd59af5.png)
過去の記事でお馴染みの「クエリビルダ」が開きます。あとはフィルター領域でクエリの対象となる”製品”、”テーブル”を選択します。
”選択”階層表示では右クリックメニューを利用して、すべてのフィールドを”出力”領域に設定します。
![Qiita 2022-02-24 Figure 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1319b98f-f406-a6ed-d0f1-55743ad95e3b.png)
”出力”領域への設定が済むと、プレビュー機能でクエリの動作確認をするか、直接OKボタンをクリックしてクエリ結果をExcelワークシート上に表示します。
クエリー名の入力を促すダイアログが表示されるので、クエリー名を入力しOKをクリックします。
![Qiita 2022-02-24 Figure 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/66127004-dac2-6555-b62d-8e031175dc7e.png)
テーブルがワークシート上に作成されます。Sharperlightのテーブル数式もアンカーセルに作成されます。
![Qiita 2022-02-24 Figure 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b91bb970-8b31-13c9-c827-b16ebd56cd94.png)
アンカーセルをダブルクリックするとクエリビルダが開き、テーブル数式の編集を行えます。
またSharperlightリボンの”クエリー”グループの”マネージャー”からも数式の編集を行えます。
”マネージャー”では、現在のワークブックに記録されているSharperlight数式の階層表示からクエリビルダを開くことができます。
![Qiita 2022-02-24 Figure 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/40ace2e2-65ba-a1f5-05d5-755c002ec86a.png)
LaravelでGoogle reCAPTUREを実装するときどれを使えばいいの？

# ざっくり探した使えそうなLaravel用reCAPTUREライブラリ


| ライブラリ | GitHub⭐ 数| |
|:--|--:|--:|
| buzz/laravel-google-captcha | 175|
| josiasmontag/laravel-recaptchav3 | 77| |
| arcanedev/no-captcha | 325| |
| biscolab/laravel-recaptcha | 345| |

GitHubスター数でarcanedevかbiscolabが使えそうな感じです。

# 
arcanedevとbiscolabのどっちが良いか、検証中。
分かったら追記します。
TomcatとServletの概要と使用開始

Tomcatはソフトウェアです、他のユーザーがコンピューターにアクセスできるようにする。

ServletはJavaコードです、ページから渡されたパラメータを受け入れる

Tomcatディレクトリ構造とは何ですか？ 各フォルダは何をしますか？
1.bin：Tomcatを実行するコマンド
2.conf：Tomcat構成ファイル
3.lib：jarパッケージ（TomcatソフトウェアはJavaコードで書かれています）
4.logs：ログデータ
5.temp：仮ファイル
6.webapps：コード


アクセス修飾子
Public
Default
Private
Protected
Azure SQL Databaseのデータベース間でSELECT INTO する方法

エーティーエルシステムズ 鍋島です。
今回は、Azure SQLデータベースで同一サーバー上のデータベース間でSELECT INTO する方法について紹介します。
SQL Serverでは問題なく別データベースのテーブルを参照出来てたので当然出来ると思い込んでいたのですが、Azureではできないことがわかりました。

* コピー元：**TESTDB01**のテーブルTable01
* コピー先：**TESTDB02**のテーブルTable01

SELECT INTOでテーブルのコピーしようとしたんですが、

```sql
SELECT * INTO dbo.Table01
FROM testdb01.dbo.Table01
```

エラーが出力されます。なんでー！（エラーメッセージを読みましょう。）

```sql
メッセージ 40515、レベル 15、状態 1、行 16
Reference to database and/or server name in 'testdb01.dbo.Test01' is not supported in this version of SQL Server.
```

どうやら、別DBのテーブルを参照できないようです。

```sql
SELECT * FROM testdb01.dbo.Test01
```

```sql
メッセージ 40515、レベル 15、状態 1、行 16
Reference to database and/or server name in 'testdb01.dbo.Test01' is not supported in this version of SQL Server.
```

そこで調べたところ、別データベースのテーブルを参照できる方法がありましたので、その手順を説明します。

#別データベースのテーブルを参照する手順

次の4ステップで参照できるようになります。

1. マスターキーを作成
1. 資格情報を作成
1. 外部リソースを作成
1. 外部テーブルを作成

以下、手順の詳細です。

## マスターキーを作成
マスターキーを作成していな場合は作成します。
このキーは、パスワードを使用して暗号化されます。

```sql:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'ここにマスターキーをコピーするためのパスワード';  
```

## 資格情報を作成
資格情報をTESTDB01USERという名前で作成します。

```SQL
CREATE DATABASE SCOPED CREDENTIAL TESTDB01USER WITH IDENTITY='ここにSQLユーザー名', SECRET = 'ここにSQLユーザーのパスワード';
--作成したクレデンシャルを表示して確認
SELECT * FROM sys.database_scoped_credentials;
```

## 外部リソースを作成
データベースを外部リソースとして参照します。
作成した資格情報 TESTDB01USER を使ってtestdb01という名前で外部リソースを作成し、
データベースを参照できるようにします。

```SQL
CREATE EXTERNAL DATA SOURCE testdb01 WITH
(
    TYPE = RDBMS,
    LOCATION = N'{ここにサーバー名}.database.windows.net', -- サーバ
    DATABASE_NAME = N'testdb01',                      -- データベース名
    CREDENTIAL = TESTDB01USER --作成した
)
```
## 外部テーブルを作成
外部テーブルの作成し、データベースから参照できるようにします。
外部テーブルと通常のテーブルの名前を同じにすることはできません。
今回はSELECT * INTO したいので、同じ名前のテーブルがあると都合が悪いので名前を変えます。
ここでは、ExternalTable01という名前に変えます。

```SQL
CREATE EXTERNAL TABLE dbo.ExternalTable01
(
    Id int Not NULL,
    Value nvarchar(MAX)  NULL
)
WITH
(
    DATA_SOURCE = testdb01,
		SCHEMA_NAME='dbo',    --スキーマ
		OBJECT_NAME='Table01' --元々のテーブル名
)
GO
```

これでテーブルが参照できるようになったので、無事SELECT INTOできるようになりました！

```sql
SELECT * INTO dbo.Table01
FROM ExternalTable01
```

# まとめ
外部テーブルを作成すると、他のデータベースのテーブルを参照できるようになって、SELECT * INTO もできるようになります！
（が、ちょっと面倒なのでサポートしてほしいな。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1760066/9e03fbeb-e1ff-280d-b573-d6ffaa24d5ea.png)
SQL データを追加、更新、削除

##データの追加
テーブルにレコードを挿入したいときはINSERTを使います。
INSERTとは「挿入する」という意味です。

```
INSERT INTO テーブル名(id,"文字",数字)
VALUES (1,"文字",数字);
```

多くの場合、idカラムにはAUTO INCREMENTという機能が使われます。
AUTO INCREMENTとは「自動で増加する」といった意味で、データが作成されるときに自動で値が割り当てられます。

```
INSERT INTO テーブル名( "文字",数字)
VALUES ( "文字",数字);
```
##データの更新
データを更新したいときにはUPDATEを使います。
複数変更したいカラムがある場合、コンマ(,)で区切ります。

※WHEREで更新するレコードを指定しないとカラム内の全データが更新されてしまいます。

```
UPDATE テーブル名 
SET カラム = 更新したい文字または数字
WHERE id = 更新したいレコード値;
```

##データの削除
レコードを削除するときはDELETEを使います。
UPDATEと同様にクエリ実行後はレコードを元に戻すことができないので、SELECTでレコードを確認してから削除を行いましょう。

※WHEREで更新するレコードを指定しないとカラム内の全データが削除されてしまいます。

```
DELETE FROM テーブル名
WHERE id = 削除したいレコード値;
```
React + Styled-components(CSS )

## 簡単な動きのあるローディング作成

以前作成した下記記事の環境からスタートします。

https://qiita.com/sh19982580/items/5f71856c7949c494d769

## リセットCSS

    import React from "react";
    import { Reset } from "styled-reset";

    const App = () => {
    return (
        <>
        <Reset />
        <h1>Hello World</h1>
        </>
    );
    };
    export default App;

`yarn add styled-reset`
今回は、Reactで使えるリセットCSSを使用
※デバイスやブラウザによってデフォルトのスタイリングがついてしまうので、忘れないためにも記載してます。

## styled-components

`yarn add styled-components @types/styled-components`

app.tsx

    import React from "react";
    import { Reset } from "styled-reset";
    import styled from "styled-components";

    const App = () => {
    return (
        <>
        <Reset />
        <StyledHello>Hello World</StyledHello>
        </>
    );
    };
    export default App;

    const StyledHello = styled.h1`
    font-size: 50px;
    text-align: center;
    `;

`yarn start`を実行し`Hello World`が真ん中に表示されていたらOK！
- `<h1>`　→　`<StyledHello>`(自分で命名可能)
- `styled.`の後に要素を指定
- バッククウォートで囲った中にCSSを記入

## ローディング

    import React from "react";
    import { Reset } from "styled-reset";
    import styled, { keyframes } from "styled-components";

    const App = () => {
    return (
        <>
        <Reset />
        <StyledHello>Hello World</StyledHello>
        <Load>Loading</Load>
        </>
    );
    };
    export default App;

    const StyledHello = styled.h1`
    font-size: 50px;
    text-align: center;
    `;

    const opacityLoad = keyframes`
    0% {
        left: 0;
        opacity: 0;
    }
    10% {
        left: 10%;
        opacity: 0.5;
    }
    30% {
        left: 30%;
        opacity: 1;
    }
    50% {
        left: 50%;
        opacity: 1;
    }
    70% {
        left: 70%;
        opacity: 0;
    }
    100% {
        left: 100%;
        opacity: 0;
    }
    `;
    const Load = styled.p`
    animation: ${opacityLoad} 2.3s linear infinite;
    font-size: 50px;
    position: relative;
    width: 300px;
    `;

`yarn start`を実行し、左から右に動く`Loading`が出ていればOK！
- `styled-components`から`{ keyframes }`を追加(アニメーション)
- 透明度を`opacityLoad`に記載して、`Load`に`opacityLoad`を追加

## 最後に
`styled-components`を導入することで、HTMLとCSSの要素を1つのファイルで見れるのは、非常に管理しやすいです。また、HTML,CSSよりもクラス名などで困ることが少ないのもメリットかなと思います。

## 参考文献

https://github.com/zacanger/styled-reset

https://qiita.com/ku1987/items/89ef25c8c59286d9a181
WSL＋venv+Djangoで作るWebアプリケーション開発環境

#目的
DjangoでWebアプリケーションを開発するにあたり、構築した環境について忘れないようにメモする。

#環境・ツール
* Windows11
* Ubuntu 20.04.3 LTS (WSLを使用）
* venv
* Django

#少し詳しく
* PCのOSはWindows11。WSLを使用してWindows11上にUbuntu環境を作り、作業はUbuntu上で行う。
* 実際のコマンド操作はVS Codeのターミナル上で行うと便利。（Remote-WSLというプラグインをVS Codeに入れることで可能）
* venvによりPythonの仮想環境を作り、Djangoはvenv上にインストールする。

![構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/ede5d967-7250-9476-4cdc-03e8292a572a.png)

Ubuntu上のフォルダやファイルは、実際にはWindows上にあるので、エクスプローラから直接操作することも可能です。

たとえば、下のようにエクスプローラ上で「D:\dev\web_app」にあるフォルダは、Ubuntu上では「/mnt/d/dev/web_app」にあるように見えます。

■ Windowsのエクスプローラ↓
![d-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/982fef25-78ea-ed83-f8e6-2c743ac5af8a.png)
■ VS Codeのターミナル↓
![d-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/2c668c02-cbff-2b1e-b9a8-fcbf9f23565e.png)
SQL テーブルの紐づけ

##テーブルの結合
JOINは複数のテーブルを1つに結合したいときに使います。ONで条件を指定して、テーブル名1にテーブル名2を結合します。結合したテーブルは1つのテーブルとしてデータを取得することができ、「ON テーブル名.カラム名 = テーブル名.カラム名」で指定します。

```
SELECT *
FROM テーブル名1
JOIN テーブル名2
ON テーブル名1.カラム=テーブル名2.カラム;
```

WHERE・GROUP BY、関数などを含んだ実行順序を確認しましょう。実行順列に関しては以下の記事を参照
https://qiita.com/yurina0402/items/78ae1f536b6755d6221a
SQLは、取得するテーブルを形成してから検索を行うので、FROM・JOINが先に行われることを覚えておきましょう。

```
SELECT 関数(カラム),カラム
FROM テーブル名1
JOIN テーブル名2
ON テーブル名1.カラム=テーブル名2.カラム
WHERE カラム = "文字"
GROUP BY カラム;
```

※JOINを使った結合は、FROMで指定したテーブルを基準に実行されます。ただし、下の図のように外部キーがNULLのレコードは、実行結果に表示されません。

####LEFT JOIN
LEFT JOINを使うことで、FROMで指定したテーブルのレコードを全て取得します。
※外部キーがNULLのレコードもNULLのまま実行結果に表示されます。

```
SELECT *
FROM テーブル名1
LEFT JOIN テーブル名2
ON テーブル名1.カラム=テーブル名2.カラム;
```

####3つのテーブル結合
JOINは1つのクエリで、複数回使用できます。JOINを複数回使用しても、FROMは1度だけ書けば大丈夫なので注意しましょう。

```
SELECT *
FROM テーブル名1
JOIN テーブル名2
ON テーブル名1.カラム=テーブル名2.カラム
LEFT JOIN テーブル名3
ON テーブル名1.カラム=テーブル名3.カラム;
```
Unity2021でUnityWebRequestでエラーが出る

Unity2021.2.10f1にアップデートしたところ、
UnityWebRequestでエラーが出力されるようになった。
（Unity2020ではエラー出ていなかった）

```
A Native Collection has not been disposed, resulting in a memory leak. Allocated from:
Unity.Collections.NativeArray`1:.ctor(Byte[], Allocator) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:69)
UnityEngine.Networking.UploadHandlerRaw:.ctor(Byte[]) (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/UploadHandler/UploadHandler.bindings.cs:95)
```

どうやら使い終わった時に明示的に **Dispose()** を呼ばないといけないようだった。

```C#
UnityWebRequest request = new UnityWebRequest(url);

... 通信処理

// 通信終了後明示的にDisposeを呼び出す
request.Dispose();
```
サイバーイミュニティ とは？

## 勉強前イメージ

イミュニティってなに・・？

## 調査

### サイバーイミュニティ とは

イミュニティとは、immunity と書き免疫という意味で、
2019年にKasperskyのCEO、Eugene Kaspersky氏によって提唱された新たな概念になります。
サイバーセキュリティより次の段階になる概念になります。

サイバーイミュニティの基本的な考え方としては、
`攻撃者にとって攻撃をしても割に合わない状態を実現する` というものになります。
攻撃者が経済的利益を目的としている場合に、被害者の損害 < 攻撃のコスト となることで攻撃の意味を無くすことにも繋がります。

### そもそもサイバーセキュリティ とは

ネットワークやデバイス、データの不正アクセスから保護する技術で、機密性・完全性・可用性を確保するための方法です。

### 現在のサイバー攻撃について

Eugene Kaspersky氏は
現在のサイバー攻撃を以下の3種類に分けて現状を以下のように分析しています。

- マルウェア

増加傾向だが、AI技術によって対応できるため深刻ではない

- 標的型攻撃

各企業によって体制強化が行われている

- 社会インフラへの攻撃

最も懸念されている問題で、社会全体がITに依存していながらもシステムに脆弱性がの残っていることが多い


特に、社会インフラへの攻撃においては被害の規模が予測不要なため、
今までのサイバーセキュリティ対策では限界があり、新たなサイバーイミュニティを提唱しました。

## 勉強後イメージ

サイバーセキュリティの次の段階で、
被害額 < 攻撃のコスト となるような環境を実現していこうってことなのかな？
概念が大きくて難しいね。

## 参考

- [サイバーイミュニティとは？概念や具体的な取り組み、今後の展望について徹底解説](https://cybersecurity-jp.com/security-measures/33988#:~:text=%E3%82%B5%E3%82%A4%E3%83%90%E3%83%BC%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3%E3%81%AE%E5%9F%BA%E6%9C%AC%E7%9A%84,%E3%81%AB%E7%B9%8B%E3%81%8C%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E8%80%83%E3%81%88%E6%96%B9%E3%81%A7%E3%81%99%E3%80%82)
- [「サイバーセキュリティからサイバーイミュニティへ進化を」--カスペルスキーCEOが提言](https://japan.zdnet.com/article/35143465/)
- [従来のサイバーセキュリティに限界　カスペルスキーCEOが示す「サイバーイミュニティ」の概念とは](https://cybersecurity-info.com/news/cyber-immunity-kaspersky/)
Power AutomateでSharePointリストの件数を取得する


PowerAutomateを使って、
SharePointリストから条件に合致するアイテムの件数を取得する方法を調べました。
以下にまとめます。

## 大きな流れ

フローの流れは以下の画像のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/a7c0eba3-1957-d456-46ad-ed03c158fd93.png)

1. 定時に実行され、(`繰り返し`)
1. SharePointリストを取得し、(`リストの取得`)
1. 該当するアイテムを取得し、(`複数の項目の取得`)
1. アイテムの件数を変数に設定し、(`変数を初期化する`)
1. 条件を設定し、
1. 最後のアクションを実行する。(画像の例では、Teamsに通知しています。)

3と4の箇所でひと手間必要になります。

## 環境

以下のようなSharePointリストがあるとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/bc23205e-ad91-883d-c5f3-cde7a92a1218.png)
列`報告日`が、今日の日付かどうかという条件をPowerAutomateでは設定する予定です。

## フロー作成

### 繰り返し

好きな時間を設定しましょう。
`繰り返し`以外のトリガーでも構いません。

### (SharePoint) リストの取得

SharePointのリストを設定しましょう。

### (SharePoint) 複数の項目の取得
ここが少し重要です。
フィルタークエリに条件を設定して、
合致するリストアイテムを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/b6d22d74-052e-4695-36e4-98945d28f8cd.png)
例えば列Dateという英語であれば、`Date eq '2022-02-23'`などとすれば良いです。
ただし日本語の場合そのままではエラーとなるため、Odataに則ったIDを設定する必要があるようです。

該当SharePointリストのページから、
右上の歯車アイコン>`リストの設定`>`列`>該当の列名をクリックしましょう。
今回の場合は`報告日`です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/2b7d4b62-1b8b-6ca6-51d6-28f2cf393a49.png)

開かれたページのURLのField=より後ろの部分が必要になります。
これと`OData_`とを合体させて、`OData__x5831__x544a__x65e5_`というような文字列を作成しましょう。
作成された文字列と現在日時とを合致するかのフィルタークエリは以下のようになります。

```
OData__x5831__x544a__x65e5_ eq 'formatDateTime(addHours(utcNow(),9),'yyyy-MM-dd')'
```
[PowerAutomateの比較演算子](https://docs.microsoft.com/ja-jp/power-automate/use-expressions-in-conditions)
[【Microsoft Flow】フローで日本時間の現在時刻を取得する式](https://qiita.com/r-wakatsuki/items/1f23d47c0bd107bc0a28)

### 変数を初期化する

一つ前のステップで複数のリストアイテムを取得したため、
関数`length`でアイテムの長さを数えましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/22d77445-3f1a-2242-f069-2b7347d68905.png)

設定値は以下のようになります。

| 項目 | 値                                         |
|------|--------------------------------------------|
| 名前 | テスト(※何でも良いですが、後ほど使います。)                      |
| 種類 | 整数                                       |
| 値   | length(body('複数の項目の取得')?['value']) |

今回は日付文字列なので整数としましたが、条件によっては真偽値(boolean)などでも良いです。

### 条件~最終アクション

変数`テスト`が0より大きいかどうか比較する条件を作成し、
はいの場合はTeamsで通知するようにします。
通知アクションの部分は各々の環境で読み替えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123580/b0680edd-bd87-a809-a942-472b03b44748.png)

終了！！

## まとめ

以上がSharePointリストの件数を取得する方法です。
件数を取得する部分で、日本語列名の設定と関数の使い方は注意が必要ですね。
もう少しそういった部分が直感的になれば、ローコードツールはもっと流行ると思うんんですけどね。

[Power Automate から SharePoint リストアイテムを取得して件数確認](https://www.illuminate-j.jp/blog/powerautomate-getitemsbysplist)
sls deployでThe stack service name 〜〜 is not valid. と出た時の対処法

# 概要
`sls create`して作ったサービスをデプロイしようとした時、
コマンド`sls　deploy`で`The stack service name 〜〜 is not valid. `というエラーが出たので、解決方法を書きます。

# エラー

> The stack service name "sls_go_project-dev" is not valid. A service name should only contain alphanumeric (case sensitive) and hyphens. It should start with an alphabetic character and shouldn't exceed 128 characters.

エラー文を読むとサービス名の制約が書かれていました。
 * サービス名はアルファベットとハイフンだけである。
 * アルファベットで始まり、128文字を超えないこと。

serverless.ymlの設定を見直しました。

# 原因
serverless.ymlの`service: `以降にアンダーバーを入れていたことが原因でした。

`sls　create`でディレクトリやその内部のファイルを一括で作成するはアラートは出ないのですが、deploy前にサービス名は変更しないといけなかったようです。

`sls create`した時は下記のようにエラーは出ませんでした。（sls_go_projectというのが今回指定したプロジェクト名でした。）

```zsh
$ sls create -u https://github.com/serverless/serverless-golang/ -p sls_go_project

✔ Project successfully created in "sls_go_project"
```

# 解決策
serverless.ymlの`service: `名のアンダーバーをハイフンに書き換えると`sls deploy`できました。

```zsh
$ sls deploy

Deploying sls-go-project to stage dev (ap-northeast-1)

✔ Service deployed to stack sls-go-project-dev (113s)

functions:
  hello: sls-go-project-dev-hello (4.3 MB)

1 deprecation found: run 'serverless doctor' for more details
```
No 'Access-Control-Allow-Origin' header is present on the requested resource. を無理やり克服する

#概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563964/e31e25a6-5d1e-4da8-f444-bc20b66408f0.png)

```
Access to image at 'https://{URL} from origin 'https://{ドメイン}' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
S3 に画像や動画を展開した際に、稀によく出るこのメッセージ。
ブラウザ上で表示は出来ているのに、javascriptで画像などを利用しようとするとエラーとなり、苦い思いもしたので備忘録として対応を残しておきます。

##症状
* 上記のエラーが出たり出なかったり。
* ブラウザを変えたり、シークレットモードで表示するとエラーが出なくなったりもする。

##原因
このエラーメッセージで検索すると、__S3のCORS設定__ や __CloudFrontのヘッダー設定__ をする
記事が多いですが、それらの設定が正常に終了しているという前提でいうと、原因は__ブラウザのキャッシュ__です。
ブラウザにキャッシュされた画像を利用した際にエラーになります。

##対策
詳しい原因はさておき、対策方法。
やっていることは単純で、パラメータを変えて三回読み直しています。

```javascript:image_load.js
function imageLoad(image_url) {
    let try_count = 3;
    let img = new Image();
    let original_url = image_url.split('?')[0];
    img.onload = () => {
        /* 画像の読み込みが終わった後にやりたいこと */
    };
    img.onerror = () => {
        if (try_count > 0) {
            img.src = original_url + '?' + Math.random().toString(32).substring(2);
            try_count--;
        } else {
            /* 画像の読み込めなかった後のこと */
        }
    };
    img.crossOrigin = 'Anonymous';
    img.src = image_url;
}
```

取り急ぎご報告まで。
OpenMP task_reduction と in_reduction の使い方

###初めに
大学のセミナーにてtask_reduction, in_reduction について調べることになったのですが、その時に日本語でこのテーマを解説しているサイトが見当たらず、テーマを理解するのに苦労しました。
もし今後自分と同様にこのテーマを初めて扱う初心者が居たら…といった感じで自分が分かった事を　初心者なりに可能な限り分かりやすくまとめてみます。　もし「ここは間違ってるよ」、「こういった説明の方が分かりやすいよ」といった場所があればご指摘していただけるとありがたいです。

###予備知識:Taskとは
OpenMPではWhileや、再帰的なアルゴリズムをTask関数によって、並列処理することが出来る。

omp pragma parallel とは違い、Taskでは、並列に行いたい処理を１つのタスクとして、タスクプールに貯蔵する。
貯蔵されたタスクは、後ほど空いているThreadが1つ1つ筒処理していく。
![Bild08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465486/190f1c27-c8b4-d6b2-210b-7233a1468980.png)

###予備知識:Task関数での関数
task タスクを作り出す
taskloop for文などをタスクで処理する
taskwait 当taskが作り出した子タスクが終了するまで待つ
taskgroup 作り出された子タスク及び孫タスク(子タスクの子タスク)がすべて終了するまで待つ

###task_reduction,in_reductionについて

task_reduction はtaskgroup に使うことが出来る
これによって、taskgroup内で作られるタスクはリダクションに参加する準備がされる

in_reduction はtask, taskloop, target(ここは自分が理解できていないので触れません)　に使うことが出来る
in_reductionが使われたtaskは、タスクの処理後にリダクションに参加する

task_reduction,in_reductionで使う(reduction-identifier:list)はreductionと同じ

reduction はtaskloopに使うことが出来て、その場合はtask_reductionがtaskgroup に使われて、in_reduction はtaskに使われた時と同じ効果を発揮する

###task_reduction,in_reductionを使った例
一見task_reduction,in_reductionの仕組みが理解しにくかったので、例を置いてみる

以下のコードは、配列の偶数の位置にいる数字を足し合わせる

![Bild06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465486/7a41f16f-a1cf-d192-0411-4377ff16dca4.png)
![Bild07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465486/bc7f1a69-60ca-5e5f-cfcb-9ffd8afebf5c.png)

taskによって、色々なタスクがタスクプール内に積み込まれて、それぞれがThreadによって処理されていく

全ての処理が終わった後、 in_reduction が指定されたタスクのみがリダクションに参加する。

firstprivateのついたタスクではsum変数はプライベート変数なので、リダクションには影響を与えない

もし、firstprivateやin_reductionを使わなかった場合は、sum変数は共用となり、競合状態となってしまう…。
なので、in_reductionが必要とされる。
チェックディスクをアンチチートツールが邪魔していた話

#概要
windowsを使っていたら突然起動時にチェックディスクを求められることはたまにある。
普通に修復されたらいいのだが、なぜかチェックディスクが始まらない。
このせいでPCを起動するたびにスキャンをスキップするには数秒以内にボタンを押してくれだとか言われてしまう。
今回この原因がRiotの開発するゲーム「Valorant」をインストールする際に必要となるVanguardというアンチチートシステムだったという話。

##起きた問題
ある日PCをつけたら突然チェックディスクを求めてきた。
これはPCを使っていたらよくあることで、問題があるドライブ名は確認できる。
またエクスプローラーを使えばドライブのプロパティ->ツール->エラーチェックをすれば問題が見つかって再起動をすることで解決することができる。
しかし以下のような状態に進まず、毎回osが起動してしまった。
![w8-chkdsk_001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239058/a5556c57-8833-ff8d-9a44-2d6a75d6f41d.jpeg)
[出典：https://www.lifeboat.jp/support/db/013170802001.html]

##チェックディスクをCMDから実行してみた
これもよくあるやり方でCHKDSK c: /fを実行した。
CMDを使ったチェックディスクの方法はたくさん記事やサイトがあるのでそちらを参照してほしい。
しかし症状は同じ。

##アンチウイルスソフトがチェックディスクを邪魔する可能性
CHKが現在のドライブをロックできない問題の修正-7つのヒント-という記事にこう書かれている。
「インストールされているサードパーティのウイルス対策ソフトウェアは、一部のコンピュータプロセスに干渉する場合があります。」
[出典：https://jp.minitool.com/data-recovery/fix-chkdsk-cannot-lock-current-drive.html]

##解決
上記の記事から私はPCに入っているアンチチートシステムVanguardが悪いのではと考え、このシステムをPCからアンインストールしてチェックディスクを実行してみた。すると通常通りチェックディスクが動作しエラーが解決した。

##まとめ
チェックディスクがうまく動作しない原因がアンチチートシステムVanguardから来ているのではと考え、アンインストールしてみるとチェックディスクがうまく動作し解決した。
この記事はVanguradを悪いシステムとして考えているわけではない。干渉するほど強いシステムではあるが、エラーが治ったら再度インストールしてValorantをプレイしてほしい。
M1マックでsublコマンドが効かない時はhomebrew経由でインストールすると使えるようになる！

# 結論
Homebrew経由でSublimeをインストールするとsublコマンドが効きます！
以下はそのプロセスです。

# 現在の問題を整理してみる

- M1Macを使用している
- Iterm2を使用している
- 自分ではPATHを通したと思っているのにsublコマンドが効かない
- 泥沼化w

調べた記事とともに問題点を探ってみようと思います。

https://qiita.com/dctakuro/items/8ac24c6f135185a9d9d2

上記記事を参考に確認していこうと思います。
# 自分のエラー内容とその解決プロセスを記録
## シンボリックリンクを貼ってみた結果

```
ln: /usr/local/bin/./subl: File exists
```

ふむ。ファイルは存在するとのこと。
では、sublコマンドを使ってみよう。

```
zsh: command not found: subl
```

え。ないって言われるんだが。

このエラーコードで出てきた記事はこちら

https://qiita.com/howaito01/items/242ba23e8a8fb00dac05

まずはパスの確認をするとのことなのでしてみました。

```
~（　🦈）:$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
/usr/local/binはある気がするね。
その次はシェルを確認するが、zshを使っていることは認識済み。

.zshrcを編集してパスと通そうとしている。
**初心者はこれをやるとファイルを壊しかねないのでやめた方がいいよね泣。**
分からなくてゴメンなさいw

でも自分はトライしてみます。
zshなので下記コマンドを実行して設定ファイルを開く。

```
vi ~/.zshrc
```

通したいPATHを追加

```
export PATH=/usr/local/bin:$PATH
```
ほんで更新

```
source ~/.zshrc
```
いや。待てよ。このパスってやっぱり通ってるよな、、、
これでできなかった場合は、下記の記事を参照とのことなので参照してみた。

https://shiro-changelife.com/error-cannot-install-in-homebrew/

homebrewを通してやるとイケる的なことを書いてあるので、早速homebrewをインストール

詳細は下記記事を参照

https://nullnull.dev/blog/how-to-install-homebrew-on-m1-mac/

ちゃんとhomebrewがインストールされているか確認

```
~（　🦈）:$ brew -v
Homebrew 3.3.16
Homebrew/homebrew-core (git revision d51a2a4a97d; last commit 2022-02-22)
```

OKです！
ちゃんと/opt/homebrewにあるか確認

```
/opt（　🦈）:$ ls
homebrew
```

いけてますね〜
次はhomebrewの中身も確認

```
/opt（　🦈）:$ ls homebrew
CHANGELOG.md    LICENSE.txt     docs            sbin
CONTRIBUTING.md Library         etc             share
Caskroom        README.md       include         var
Cellar          SECURITY.md     lib
Dockerfile      bin             manpages
Frameworks      completions     opt
```

OK
次はPATHが通っているか再度確認する

```
~（　🦈）:$ echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```

いけてる！
ではhomebrewでSublimeを再インストールしよう！
※元からあるSublimeアプリは削除済みです。
GUIのアプリケーションを管理・インストールするにはhomebrew-caskをインストールするといいみたい。
してみよ

```
$ brew tap caskroom/cask
Error: caskroom/cask was moved. Tap homebrew/cask instead.
```

どうやら現在のコードは少し違うみたいなので下記コマンドを入力

```
$ brew tap homebrew/cask
```

インストールできたのかを確認

```
Homebrew 3.3.16
Homebrew/homebrew-core (git revision c17eba84fd1; last commit 2022-02-23)
Homebrew/homebrew-cask (git revision c4ebeedb14; last commit 2022-02-23)
```

それでは、Sublimeをインストールします

```
$ brew cask install sublime-text
Error: `brew cask` is no longer a `brew` command. Use `brew <command> --cask` instead.
```

とのことなので、下記コマンドに変更

```
$ brew install --cask Sublime-text
```

できました〜！
最後に念願のSublコマンドを入力してみる。

```
~（　🦈）:$ subl
```

いけました！！！！
ぜひ、Sublコマンドが使えない方はhomebrew経由でやってみてください！
Scrapy でノードを取得する方法

- `Response` オブジェクトの `css()`メソッドでノードを取得できる。
- `css()`メソッドの戻り値は `SelectorList` オブジェクト

## `SelectorList` オブジェクトの主なメソッド

メソッド | 内容 
--- | ---
`getall()` | ノードの一覧を文字列の`list`として取得する
`get()` | ノードの一覧の最初の要素を文字列として取得する<br>※HTMLタグを含む文字列が得られるのでテキストのみを取得したい場合は、`::text` 擬似要素でテキストのみを取得してから `get()` を適用する
`re(regex)`|ノードの一覧のうち、引数に指定した正規表現(regex)にマッチする最初の部分を文字列として取得する
`css(query)` | ノードの一覧の要素に対して、引数に指定したCSSセレクター(query)にマッチするノードの一覧を `SelectorList` として取得する
`xpath(query)` | ノードの一覧の要素に対して、引数に指定した XPath(query)にマッチするノードの一覧を `SelectorLiset`として取得する。
Scrapy Shell の使い方

## Scrapy Shell とは
Scrapy のためのインタラクティブシェルで、CSS セレクターや XPath による抽出を簡単に試せる。
通常の Python のインタラクティブシェルと同様に Python のコードを実行できる。

### 起動方法
`scrapy shell` コマンドに URL を引数として与えることで起動。

```bash
$ scrapy shell https://****/****/****
```

## 関数

関数|内容
--- | ---
`shelp()`| Scrapy Shell のヘルプを表示する。
`fetch(url[, redirect=True])`<br>or<br> `fetch(req)` |引数で指定した URL または `Request` オブジェクトのページを新しく取得し、`request` や `response` などの変数の値を置き換える。
`view(response)`|引数で指定した `Response` オブジェクトをブラウザで表示する。
Seleniumで認証プロキシを突破する方法

組織内でSeleniumを使用する場合Proxy認証が壁となる。調べた結果、Selenium自体の機能により突破することはできないことがわかり、代替案についての数多くのアイデアが紹介されている。各案をトライ&エラーし解決まで非常に時間を要した。
結論として、Selenium-wireがやりたいことに近く最もシンプルだったのでこの方法を採用。気になる点として、webdriverの導入をSelenium-wireから行っており、これが通常のSeleniumと比べ、今後どういう影響があるのか不透明である。

Selenium-wireを使ったProxy認証の突破方法
https://www.youtube.com/watch?v=d8voxp-4Uf8
※Selenium wireをcondaでインストールできず、仕方なくPIPでインストール。混ぜるな危険と聞いており恐る恐る。仮想環境でやってるから大丈夫か？以下URLでCondaでのinstallを記載しているが、できなかった。https://anaconda.org/ralexx/selenium-wire

他の案としては（１）Pyautoguiの使用、（２）Chrome の拡張機能でProxy情報を入れる方法、がある。前者は表示されたプロキシ認証ポップアップに対して、pyautoguiで入力する強引な方法である。この場合プログラムを立ち上げてプロキシを突破するまでの間はPCを操作することができない。またポップアップを表示させないといけないのでヘッドレスモードも不可。

後者はjsファイルをZIP ファイルに格納しChrome拡張機能で取り入れる方法が各所で紹介されているが、当方の実力不足もあり実装できなかった。
https://stackoverflow.com/questions/55582136/how-to-set-proxy-with-authentication-in-selenium-chromedriver-python
https://www.guru99.com/selenium-proxy-authentication.html

他にProxy helperという拡張機能を導入し、Webdriverの立ち上げOptionとしてとりこんでみたが、動作が安定しなかった。中途半端にうまくできたため、この方向にこだわってしまい時間を消費する結果となった。導入に際して拡張機能のPackage化が必要だったりと、調べることが多かった。
2022/2/24主にITとかセキュリティの記事

BlackBerry端末復活プロジェクト、頓挫(2/22)
https://www.itmedia.co.jp/mobile/spv/2202/22/news087.html

App Storeに本物にそっくりの危ない“偽アプリ”が存在！(2/22)
https://iphone-mania.jp/news-439583/

ユーザーエクスペリエンス創造にレイテンシ無用！
マルチCDNの実際のメリットと障壁(2/22)
https://b-library.impress.co.jp//ud/product/code/WD-2022-0015

報道発表資料　大阪市住民基本台帳等事務システムの不具合について(2/22)
https://www.city.osaka.lg.jp/hodoshiryo/shimin/0000559828.html

第171回：米国企業の取締役がサイバーセキュリティに取り組む上での課題(2/22)
https://www.risktaisaku.com/articles/-/65311

ウクライナ東部で「欧州向け世界最大のパイプラインが爆発」と不正確な情報が拡散(2/21)
https://www.buzzfeed.com/jp/kotahatachi/ukraine-russia-pipeline

連載［タブレット学習　読者の声］＜下＞デジタル世代
学ぶ姿勢　会得に期待(2/22)
https://www.niigata-nippo.co.jp/articles/-/29572

スパイ容疑の日本人を「獄中死」させている中国が日本の情報を抜きまくる皮肉(2/22)
https://www.mag2.com/p/news/529797

Windows 11の最小システム要件を満たさないPC、デスクトップに警告表示へ？(2/22)
https://iphone-mania.jp/news-439560/

周波数スペクトル、通信範囲、およびネットワークトポロジ(2/22)
https://news.mynavi.jp/techplus/article/wirelesstechnology-1/

JVN#67108459
EC-CUBE 用プラグイン「メルマガ管理プラグイン」におけるクロスサイトリクエストフォージェリの脆弱性(2/22)
https://jvn.jp/jp/JVN67108459/

セカンドレイヤーとサイドチェーンは何が違うの？仮想通貨に関する素朴なギモンに答えます(2/22)
https://hedge.guide/feature/difference-between-second-layer-and-sidechain-bc202202.html

【JSA規格】「JSA-S1013　スマートワーク－テレワークを含む働き方改革のための指針」を開発・発行(2/22)
https://prtimes.jp/main/html/rd/p/000000114.000004052.html

Dropbox（ドロップボックス）とは？調査して分かった評判・メリット・注意点を解説！｜テレ東プラス(2/22)
https://www.tv-tokyo.co.jp/plus/smp/business/entry/2022/025507.html

日本企業が進めやすい「サイバーディフェンスセンター」の設置　X.1060実現に向けたアプローチとは【第3回】X.1060の構築プロセスとマネジメントプロセス(2/22)
https://enterprisezine.jp/article/detail/15552

Googleカレンダーのリマインダーの使い方｜リマインダーの作成方法とは【Google活用基本のき】 | サライ.jp｜小学館の雑誌『サライ』公式サイト(2/21)
https://serai.jp/living/1055848

「サイバーセキュリティ」セミナーが開催されます(2/22)
https://www.shikoku.meti.go.jp/01_releases/2022/02/20220222a/20220222a.html

App Storeで詐欺アプリ発見！人気の二要素認証アプリを模倣し高額課金(2/22)
https://www.appps.jp/362668/

ドイツ銀、ワッツアップのメッセージを削除しないようスタッフに指示(2/22)
https://www.bloomberg.co.jp/news/articles/2022-02-22/R7OKLBT0G1P201

JVN#53871926
EC-CUBE における HTTP Host ヘッダの処理に脆弱性(2/22)
https://jvn.jp/jp/JVN53871926/

ＭＵＦＧ、ブロックチェーン活用の次世代決済事業を１年で停止へ(2/22)
https://www.bloomberg.co.jp/news/articles/2022-02-22/R7P2Z2T1UM0Z01

ハイブリッドワークにはどんなリスク？ 新様式に即したセキュリティ対策を(2/22)
https://active.nikkeibp.co.jp/atcl/wp/b/22/02/15/02301/

Apple製以上の機能を持つAndroid用のAirTag発見アプリ、学生が開発(2/22)
https://iphone-mania.jp/news-439470/

滋賀県のデジタル商品券、不正アクセス相談900件超　クレカ利用明細確認を(2/22)
https://www.kyoto-np.co.jp/articles/-/737655

さくらのクラウドサービスに障害　利用企業10社以上に影響か(2/23)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031800050/021600036/

データが相手に届くまで(2/23)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800010/021600049/
強化学習を使ってfx取引を学習する

# 作ったもの
https://github.com/komo135/forex-trading

fxの過去のデータを利用して強化学習を使って自動取引を学習させること目標にします。詳しいコードは上記のリポジトリを参照してください。

# データの準備
1. Mettrader5をインストールします
1. デモアカウントかリアルアカウントを作成します
1. pythonでMetatrader5パッケージをインストールします
```console
pip install Metatrader5
```
そして以下のコードを実行します。
```console
cd data
python gen_data.py
```

# 実行
```python
from agent import dqn
agent = dqn.Agent(model_name="efficientnet_b0", s=5, action_type=3, pip_scale=1, n=1, loss_cut=False, use_device="tpu", dueling=False)

agent.run()
agent.plot_result(w=self.best_w, risk=0.04, s=self.s)
```

# 結果
これは違うデータによるものです
![FireShot Capture 002 - forex-trading_dqn.ipynb at main · nagikomo_forex-trading - github.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130763/7454b935-82fe-1437-d603-2e946cafa802.png)
ARC034 B問題を解説する。 (PythonのACコードあり)

#ARC034 B問題 方程式
##問題
たとえば、$f(5391)=5+3+9+1=18$ のように、各桁の和を関数$f(x)$で定義する。
$1\leq N\leq 10^{18}$を満たす$N$が与えられるので、$x+f(x)=N$となる$x$を求めてください、という問題。

https://atcoder.jp/contests/arc034/tasks/arc034_2

##考察その1　xの上限は？

たとえば、$N=100$のとき、$x$は$100$以上の値をとりません。$100+f(100)>100$だからです。
どのような$N$が与えられても、$x<N$であることは間違いなさそうです。
これで$x$の上界が分かりました。

##考察その2-1　xの下限は？
次に$x$の下限を考えてみます。
$N$の最大値は$10^{18}$なので、$x$を$1$から順番に全探索するとTLEになってしまいます。
もし実際に手計算で解くとなったときに、問題から$N=10^{18}$を与えられたら、だれも$x=1$から順番には計算していかないはずです。$10^{18}$よりも少し小さいところをくまなく探してみるんじゃないでしょうか。
この「少し小さい」がどの程度の数なのかを考えます。

##考察その2-2　xの下限を求めていく
$x+f(x)=N$より、$x=N-f(x)$です。
たとえば、$f(x)$が$100$以下の値しかとらないことが分かっていれば、「$x=N-101$かなー？」と計算する必要がなくなります。
つまり、どれくらい下まで探索すればいいのかは、$f(x)$の最大値を求めるのと同じことになります。
$1\leq{N}\leq10^{18}$の範囲で、各桁の和が最大の数を考えると、9が18個だけ続いた数$99999999999999999$が最も大きくなりそうです。
実際には、$99999999999999999+f(99999999999999999)>10^{18}$となり、この数が答えになることはないですが、$f(99999999999999999)=9×18=162$で、$x=N-162$よりも下に答えがないことが分かりました。

##考察その3　まとめ
正整数$N$が与えられたとき、
考察その1より、$x<N$、すなわち、$x\leq{N-1}$
考察その2より、$N-162\leq{x}$
２つを合わせて、$N-162\leq{x}\leq{N-1}$
この範囲で計162回の探索をすれば答えが出ます。

##おまけ(ACコード)

``` Python
def main():
    N=int(input())
    anslist=[]
    for i in range(1,163):
        x=N-i
        if x<0:
            break
        pl=0 #f(x)=pl
        sx=str(x)
        for k in sx:
            pl+=int(k)
        if pl+x==N:
            anslist.append(x)
    anslist.sort()
    print(len(anslist))
    for a in anslist:
        print(a)

if __name__ == '__main__':
    main()
```
Alteryxの分岐ツールの使いどころ

Alteryxには分岐ツールというのがツールがあります。
とっつきにくいツールだったので、備忘録もかねて。


## 分岐とは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/669201b7-dd95-a0d1-ec92-8abd77afcb9e.png)


例(ヘルプ)をみると
>分岐ツールを使用して、ワークフロー内のデータパスを変更します。
分岐終了ツールは、分岐ツールから生じる2つのパスを結合して、処理を単一のデータストリームに返します。

と書いてありますが、要は処理のスキップができるようになるということですね。

## データの流れを見ていきましょう
チェックOFFでは「L」にしかデータが流れないですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/973755b8-5198-bb66-153d-7f3d5c66e26c.png)


一方チェックONでは「R」にしかデータが流れません。何も処理しないということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/7712860c-da5b-9892-a2be-799a1db06443.png)


## フィルタツールで同じことできるじゃん？？
フィルターツールでも同じことはできますがTrue/False両方データが流れてため、分岐終了後のデータに違いが出てきます

例えばフィルタ条件をIDが10以下で分岐した場合は
inputデータではIDは10以下しかないため、全データ「T」に流れますね。
でも、「F」はデータがないが処理としては流れるため、最後ユニオンする際にヘッダ情報があり余計なヘッダが出現してしまいます。
（※この辺もどうにかすることはできますが、今回はやりません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/06ab3688-a23c-ea59-c5da-f16dff23387b.png)


## フィルタツールと分岐ツール違い

|  |分岐ツール| フィルタツール |
|:-:|:-:|:-:|
| 出力(Ture/False)  | どちらかのみ  |両方   |
|  分岐条件 | ON/OFFパラメータ  |  インプットデータから |
|使えるフロータイプ  | マクロやアプリ|全フロータイプ   | （）

分岐ツールの特徴としてはインプットデータから判定するわけではなく、別でパラメータを受けっとってON/OFFの分岐をします。
このパラメータについてはインターフェースツールを使って設定になるため、マクロやアプリで使用するということになります。
※通常フローで使用する場合もありますが、特殊なので別の機会で紹介できればと思います

## インターフェースツールを使った実際の設定例
チェックボックスで行う場合は以下のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/e3ff8ef2-e349-4030-f257-33dcac2e5301.png)

アプリで実行する画面は以下のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/130ceb48-873b-c145-a5d9-cb074f195732.png)

## どんな時に分岐ツールを使うのか？
いくつかあると思いますが、例えばこんなもの。

* データフォーマットを変えたい　⇒　CSVとかExcelとかyxdbなど選んだフォーマットで出力
* カラムを変えたい　　　　　　　⇒　部署によって必要項目が違う

データフォーマットを変えたい場合の例（無理に分岐終了ツールはいれなくても大丈夫）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391923/348a3d79-7837-7aad-a8de-68af015c9df4.png)

この分岐のやり方では2つの分岐までしかできなきですが、もっと分岐を増やしたい場合にどうするの？ということがあるのでそれはまた別記事にしたいと思います
若手エンジニアがマネージャー側になるための考え方

# はじめに
夜中にお酒を飲みながらネットサーフィンしてたら、急に何かを書きたくなったので、書いてみました。
初めての投稿ですのでお手柔らかに。。。

4年目で小さい規模ですがPMをやり始めたので、1年目2年目の方でPMとか目指したいって人向けに、
どんな事を意識してきたかを共有できたらと。

# 自己紹介
本題に入る前に、私がどんな奴なのかを簡単に紹介します。。。
### エンジニアとしてのキャリア
2018年に新卒未経験でSESの企業に入社。
javaの研修を経て現場配属。配属2日目にPMに詰められる。
その後なんやかんやあって2年目入るか入らないかくらいでSVを始めて、なんやかんやで4年目入るか入らないかくらいでPM始める。

# PMの役割
本題に入る前に、PMってどんな役割なのかを私なりの解釈を書いておこうと思います。
ここに至るまでにどんなことを意識していくのかをイメージしてもらえればと思います。

- チームが最大限効率よく成果を上げれる状態を作ること
    - システム開発は基本的にチームプレイ
    - ゴール(案件の完了)までの最短を考えると、チームの成果を最大限に生かすことになる
    - 生産的な作業に集中できるようにし、手戻りを少なくすることが効率につながると思っています
- 案件を円満に完了できるように調整すること
    - 案件によってはPMが直接顧客とやり取りをしたりすると思います
    - 顧客もチームも円満に案件を完了できるように各所の調整をすることが必要になってくると思います

# PMまでのフェーズと意識
私もPM初めて1年くらいですのでまだまだこれからですが、ここに至るまでいくつかのフェーズがある様に思ったので、
フェーズごとにどんなことを意識してきたかにフォーカスして書いていければと思います。
### PMに至るまでのフェーズ
ここではあくまで、チーム内での役割にフォーカスして考えます。
PGやSEといった技術的な視点は度外視します。
あと、フェーズの名前も適当につけてるので、ここではそういう名前にするよって感じです。

- ジュニアクラス
    - 研修後の配属されたて
    - まだ一人で作業ができないくらい
- メンバークラス
    - 一人前に作業ができるようになってきたくらい
- SVクラス
    - 数人のメンバーの管理をし始めるくらい
    - 進捗管理やフォローをしていく

### それぞれのフェーズでの意識
#### ジュニアクラス
このクラスはまず一人前に作業ができるようになることを目指しましょう。
一人前とは、「早くコードが書ける」とか「ググらなくても作業ができる」とか「xxxができる」といった具体的な数値ではなく、
チームから求められているタスクを一人でこなせるようになることだと思っています。
その結果、早くコードを書かなきゃいけないとかっていうことが求められてくるのかと。
チームからの期待値に同等かそれ以上で答えられるようになることですね。
#### メンバークラス
このクラスはほかの作業者の様子やPJの様子を気にできることを目指しましょう。
ある程度作業ができるようになってくると、心や脳のリソースにゆとりが生まれてくるかと思います。
その時に、「楽だからこのままでよいやー」とならずに、「この人って今何やってるのかな」とか「このタスク遅れ気味だけど大丈夫かな」とかを気にできるようになるとよいかと思います。
さらに良いのは、自らフォローに動けたり、SVやPMと相談できるようになるとよいかと思います。
#### SVクラス
このクラスは、顧客が求めていることとチームの状況、政治的な要素を加味して何をどのようにコントロールすると、案件が円満に完了できるかを考えられることを目指しましょう。
このクラスの人は基本的にPJのタスクをコントロールすることはできるようになっていると思います。
PMへの道として、顧客目線や経営層、営業的な視点を持ちつつ、チームが最大限の成果を上げれるようにすることが必要になると思っています。
開発体制を整えるだけでもダメ。顧客の言う通りにするだけでもダメ。会社的な都合を丸のみするのもだめ。
 ~~すべてを絶妙にコントロールすることが必要だと思います。~~ 
商流や、お客さんとの契約次第でもありますが、ボトルネック、ステークホルダ、どこにどのようなアプローチをしたらよいのかを考えるとよいかPMと相談できるようになるとかですかね。
ここが一番難しいところでもあると思いますが。

# まとめ
色々思うがままに書きましたけど、とりあえずは「自分の作業をこなしつつ、周りの様子をうかがえるようになる」が第一ステップだと思います。
そこからはPJを炎上させないことを考えると自然と身につくと思います。
まずはメンバークラスで周りも意識できる、SV的に助かる要員を目指すとよいのかなと思います。

# あとがき
途中でお酒なくなって飽きてきちゃいました。すみません。
思うがままに書いてみましたけど、やっぱりちゃんと構成を考えないとだめですねぇ。
読みやすいドキュメントを作れることも必要なスキルなので磨いていきたいと思います。
また気が向いたら何か書くと思います。

ここまで見てください、ありがとうございます。
四角形を検出する

#画像内の四角形を検出する方法です
![スクリーンショット 2022-02-24 2.58.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/11f0f324-7bb5-90f4-c0e8-9d6b79d53659.png)

#書類や標識の検出に

四角形の人工物を検出できれば、場面に応じて様々な用途に活かせそうです。
例えば、ドキュメント内の四角形の検出など。

#Visionの四角形検出が使える
。

#方法

画像にVNDetectRectangleRequestをするだけです。

```swift
let request = VNDetectRectanglesRequest()
let handler = VNImageRequestHandler(ciImage: ciImage!, options: [:])
try! handler.perform([request])
guard let results = request.results else { return }

for result in results {
    print("topLeft: \(result.topLeft)")
    print("topRight: \(result.topRight)")
    print("bottomLeft: \(result.bottomLeft)")
    print("bottomRight: \(result.bottomRight)")
    print("boundingBox: \(result.boundingBox)")
}
```

>topLeft: (0.37335851788520813, 0.5885436534881592) 
topRight: (0.5980302095413208, 0.6653665900230408)

>bottomLeft: (0.45727139711380005, 0.16498719155788422) 
bottomRight: (0.7020156383514404, 0.26323217153549194)

>boundingBox: (0.37335851788520813, 0.16498719155788422, 0.3286571204662323, 0.5003793984651566)

画像内の正規化座標を取得できます。
Y座標は、画像の下が基準になっています。


![スクリーンショット 2022-02-24 2.30.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/74aae1d6-9f8c-3d39-81bb-e89103006ad5.png)

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
ロジックサマナー  ランクC「圧縮」(Python3) を解いた


# はじめに

**[ロジックサマナー](https://paiza.jp/logic_summoner/)というプログラミング学習サイトの問題の一つです。**

解けるやろって適当に思ってたら、全然正答できなくて悩んでました。数日経っても、意地張って解こうとしましたが、解けなかったです。
そこで答えを探したんですが、欲しいコードがなかった。
なので、私が正答したソースコードをここに載せます。


# 問題の概要

[問題はここにあります](https://paiza.jp/logic_summoner/challenges/logics_type_2001)

#### 制約はこちら
> 入力される値
> S

> 条件
> ・1 ≦ ( S の長さ) ≦ 100
> ・S には "w"(白) か "b"(黒) の文字しか含まれない

#### 入出力例
```
入力:  "bbbwwwww"
出力:   3 5

入力:  "wwwwwbbb"
出力:   0 5 3
```
このように、w(白)から始まった場合は、0 を入れなきゃいけない。


# 正答したソースコード

実装はPython3で行いました。中には PHP や C# で書かれた正答のコードを見かけたんですが、私には読めなかったので、見るのは断念しました。。。


以下、正答した私のソースコードです。

```python3
string = list(input())
string.append('\0')
count = 0

if (string[0] == 'w'):  # 最初が白なら、"0"と出力する
    print("0 ", end="")

i = 0  # 配列の場所を示す

judge_str = string[0]  # 一つ前の文字を記憶しておく
while (i < len(string)):
    if (string[i] == judge_str):  # 数え上げの処理
        count += 1
        i += 1
    else :  # 異色やった場合の処理
        print(count, end="")  # ひとかたまりを抜けた一つ目
        count = 0
        judge_str = string[i]  # 記憶する
        if (i + 1 >= len(string)):
            continue
        print(' ', end="")  # '_'とかで空白を可視化したら、デバッグしやすいかも
print()  # 改行
        
```
私がC言語からプログラミング始めたからか、書き方的にC言語とかでも同じように書けると思います。


# ソースコードの説明
```python3
string = list(input())
string.append('\0')
count = 0
```
ここでは、単純に文字列の後ろにアクセスできる配列を用意したかっただけですね。
'w'or'b'以外だったら、上記のコードで動くと思います。

```python3
if (string[0] == 'w'):  # 最初が白なら、"0"と出力する
    print("0 ", end="")

i = 0  # 配列の場所を示す
```
これは、最初の文字がw(白)だったら、0 と出力してます。
i は、配列の番号を示す変数です。

```python3
judge_str = string[0]  # 一つ前の文字を記憶しておく
while (i < len(string)):
    if (string[i] == judge_str):  # 数え上げの処理
        count += 1
        i += 1
    else :  # 異色やった場合の処理
        print(count, end="")  # ひとかたまりを抜けた一つ目
        count = 0
        judge_str = string[i]  # 記憶する
        if (i + 1 >= len(string)):  # '==' でもよかったけど、気持ち的に
            continue  # breakでもよかったかもしれん(検証してません)
        print(' ', end="")  # '_'とかで空白を可視化したら、デバッグしやすいかも
print()  # 改行
```
実際の入力が bbbwwwbwwbbbbb... といった具合に、wとbが繰り返し入力されるので、ループを用いて処理します。（最初、繰り返されると思ってなかった）

３行目でNULL文字を追加したのが活きてます。
else文の中で、圧縮した値を出力してます。

# まとめ？
最後の最後っていうあたりで数日粘りました(多分)。結局、自力で解けました。
対ありです。


変数名の命名がクソって思うので、どなたかいい命名方教えてください...
あと、ソースコードの書き方わかりやすいかどうかも教えてください。 以上