IECフリッカについて(メモ)

メモ

たぶんエルサルバドル大学の文献が、規格書まんまだと思うから、
ここからコードに落とすか・・・。

エルサルバドル大学 Diseño y construcción de un prototipo de laboratorio del flickermeter IEC 61000-4-15
https://ri.ues.edu.sv/id/eprint/3845/1/Dise%C3%B1o%20y%20construcci%C3%B3n%20de%20un%20prototipo%20de%20laboratorio%20del%20flickermeter%20IEC%2061000-4-15.pdf

e・オータマ 電源高調波電流の制限 — IEC 61000-3-2, -3-12 の概要
https://www.emc-ohtama.jp/emc/doc/iec61000-3-2-explained.pdf

e・オータマ 電圧変動やフリッカの制限 — IEC 61000-3-3、-3-11 の概要
https://www.emc-ohtama.jp/emc/doc/iec61000-3-3-explained.pdf

横河計測 電圧変動/フリッカ測定ソフトウエア ユーザーズマニュアル(IEC 61000-3-3対応)
https://cdn.tmi.yokogawa.com/IM761921-07.jp.pdf

横河計測 WT5000用電圧変動/フリッカ測定ソフトウェア(IEC 61000-3-3対応) ユーザーズマニュアル
https://cdn.tmi.yokogawa.com/18/8226/files/IMD024-02JA.pdf

日置 電源品質アナライザ3196 取扱説明書
https://www.hioki.co.jp/file/cmw/hdInstructionManual/90918/pdf/?action=browser&log=1

九電テクノシステムズ フリッカメータ IFK-40
https://www.q-tecno.co.jp/images/flickermeter/IFK-40catalog0701.pdf

PB180Dに2107F用のスタンドを付ける

ポータブルバンドソー
www.makita.co.jp

マキタ(Makita) ポータブルバンドソー ハンディタイプ 2107F
https://www.amazon.co.jp/dp/B0009OMYDI/

マキタ(Makita) ポータブルバンドソー用スタンド 194025-5
https://www.amazon.co.jp/dp/B00PJOH6E0/

アマゾン見てると,充電式のやつでもスタンド付けられるぞっていう猛者がいたので,
チャレンジ!!!

ねじを緩めます。
f:id:iinebot:20210810115803j:plain

カバーを外し,4か所緩めます。
f:id:iinebot:20210810115941j:plain

スタンド取り付ける側を外します。
f:id:iinebot:20210810120553j:plain

スタンドを用意して・・・
f:id:iinebot:20210810120439j:plain

肉厚のところにタップを切っていきます。
f:id:iinebot:20210810121008j:plain

適当なクランプで固定しながら
f:id:iinebot:20210810121111j:plain

下穴をあけて,
f:id:iinebot:20210810121146j:plain

タップ(M8)をきる!
f:id:iinebot:20210810121221j:plain

てってれーん!
f:id:iinebot:20210810121256j:plain

あとは逆手順で元に戻して,
スタンドに付属の蝶ねじで固定すればOK!!!

できた!

MediaStoreを使ってDCIMディレクトリに画像を保存する

事の発端
Environment.getExternalStorageDirectory()がDeprecated!!!
頼むぜ,google・・・。
それ今から辞めたら影響度でかくない?
API level 1のときからだぜ?
今,30とか31だぜ?APIがYO!!!

ここに書いてある通りなんだけど・・・
qiita.com

アプリ内データはgetExternalFilesDir()とかで代替できるんだけども,今まで普通にアクセスしてた写真フォルダとかにはアクセスできなくなってくるわけなんですよ。
というわけで四苦八苦しながら解決いたしました。

MainActivity.java

package jp.co.hogehoge.mediastoretest;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Bitmap bmp;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = findViewById(R.id.imageView);
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic);

        button = findViewById(R.id.button);
        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        if (view == button) {

            ContentValues contentValues = new ContentValues();
             // ファイル名
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "sample2.jpg");
            // MIMETYPEの設定
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            // 書込み用にロックする
            contentValues.put(MediaStore.Images.Media.IS_PENDING, 1);
            //保存フォルダ ->DCIMディレクトリのtestに格納される(フォルダも自動で作ってくれる)
            //Environment.DIRECTORY_DCIMをEnvironment.DIRECTORY_PICTURESにすればPicturesディレクトに保存される
            contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM+"/test/");
            ContentResolver resolver = getApplicationContext().getContentResolver();
            
            Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
            Uri item = resolver.insert(collection, contentValues);

            try {
                OutputStream outPutStream = getContentResolver().openOutputStream(item);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                //ByteArrayOutputStreamに変換する
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
                //ストリームからバイトにして
                byte[] bytes = byteArrayOutputStream.toByteArray();
                // OutPutStreamに流し込む
                outPutStream.write(bytes);
                outPutStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            contentValues.clear();
            // ロックの開放
            contentValues.put(MediaStore.Images.Media.IS_PENDING, 0);
            resolver.update(item, contentValues, null, null);
        }
    }

}

AndroidManifest.xml

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:background="@drawable/ic"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="128dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

BUTTONを押すと・・・。
f:id:iinebot:20210622192544p:plain


DCIMのテストディレクトリに保存されました!
f:id:iinebot:20210622192604p:plain


参考

akira-watson.com

www.fixes.pub

matsudamper.hatenablog.com

onActivityResult()がdeprecatedな件について

google許さん!
しかもkotlinしかサンプルが見当たらない!!!
もうjavaは卒業しないといけないのかもしれない。

buildersbox.corp-sansan.com

ちなみに色々やってみたけど,
できなかったwww
↓失敗作

   private int CREATE_FILE = 1001;//リクエストコード

    //onActivityReslutのかわり
    ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                    if (result.getResultCode() == CREATE_FILE)
                        Log.d(TAG, "CREATE_FILE");
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        if (result.getData() != null) {

                            Uri uri = result.getData().getData();
                            Log.d(TAG, "mStartForResult -> " + uri.toString());
                        }
                        //
                        //Intent intent = result.getIntent();
                        // Handle the Intent
                    }
                }
            });

MQLとC#について

はじめに

まあ,うまくいかないわけですよ。
最初実は,

fx-dollaryen.seesaa.net

こっちの記事見ながらやってたんですが,
うまくいかないわけですよ。

問題点

nugetからUnmanaged Exportsを利用する際にそのままやると2つエラーがでます。

  1. error : syntax error at token '{' in:
  2. error : Microsoft.Build.Utilities.ToolLocationHelper could not find ildasm.exe.

です。
この2つは別々の原因によって発生しているので,原因を切り分けて進めていく必要がありました。

環境

Windows 10 20H2
Microsoft Visual Studio Express 2017 for Windows Desktop 15.9.29

error : syntax error at token '{' in:について

これはマルチバイト文字に関するエラーのようで,ネットの記事をみると,Unicode対応ではないプログラムの言語をENにしてねってありますが,自分の環境ではエラー吐いたままでした。
なので,そんなことよりパソコンの言語をEN(US)とかに変えたところエラー解消しました。

f:id:iinebot:20201208200459p:plain

error : Microsoft.Build.Utilities.ToolLocationHelper could not find ildasm.exe.について

なんかよくわかんないですが,何かが違って実行ファイルが見つからないようです。
これは,nugetライブラリの作成が古いことが原因のようで,UnmanagedExports.Repackってやつをnugetからインスコすると解決しました。

f:id:iinebot:20201208200441p:plain

MQL4側の処理

紆余曲折あってDLLの名前を考えている余裕もなかったので・・・。

//+------------------------------------------------------------------+
//|                                                      dllTest.mq4 |
//|                                        Copyright 2020, InvestorX |
//|                                  https://iinebot.hatenablog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, InvestorX"
#property link      "https://iinebot.hatenablog.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window

#import "ClassLibrary4.dll"
   int  Plus(int left, int right);
#import
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

   
   Print(IntegerToString(Plus(1,2)));
//--- return value of prev_calculated for next call
   return(rates_total);
  }

ひたすら3とPrintし続けるあふぉなインジが完成しました。
f:id:iinebot:20201208201000p:plain

おわりに

ロンドさんの記事にコメントしているKさんの言ってるように
public static int

public unsafe static int
に変更しプロパティでアンマネージドをクリック
はしといた方が良いかもしれません(未検証)。

目的は果たせたのでとりあえず終了!

ケースファンについて

ケースファンに関するぼくなりの考え方です。

1.単位換算について

1 [m3/h] = 0.589 [CFM]
1 [mmH2O] = 9.8 [Pa]
1 [Pa]=1 [N/m2]

2.ノイズについて

noctua のホームページにはdB/Aと記載されていて、一般的な騒音測定のことを指します。他メーカも同様だと思いますので、一律に比較して良いものと思われます。

20[dB] 木の触れ合う音(ほとんど聞こえない)
30[dB] 郊外の深夜(小さく聞こえる)
40[dB] 図書館(聞こえる会話には支障なし)
50[dB] 静かな事務所(大きく聞こえる、通常の会話は可能)
60[dB] 静かな乗用車(非常に大きく聞こえうるさい、声を大きくすれば会話ができる)
70[dB] 電話のベル(非常にうるさい)
80[dB] 地下鉄・電車の車内(うるさい)
朝日スチール工業株式会社より

主観によるものなので、どの程度まで雑音を許容できるかというところになってくると思いますが、50[dB]も出ているパソコンはうるさく感じる人が増えるレベルではないかなと思います。
ただ、ケースファンについては、さらに箱の中に入れるということを考慮するともう少し許容しても良いかもしれませんが、静音志向のケースではない限り大幅なノイズカットは期待できないので、個人的には、ファン単体で30[dB]を超えないようにパーツを選んでいます。
また、20[dB]増えるごとにノイズの大きさは10倍増えていくので、見た目の数値の増加に比べ大きさが大きくなることを注意して頂きたいです。

ascii.jp

上記は、サイコムで出しているSilent Master NEOシリーズの企画記事です。これによると一般的な静音パソコンのノイズは36.9[dB]で図書館よりは静かで日本建築学会編 / 建築物の遮音性能基準と設計指針によれば、小さく聞こえる程度のようです。サイコムの方は、非常に小さく聞こえる程度のようです。寝室の近くに置く場合は、この程度の音が望ましいと思います。
(特にこのシリーズを推しているわけではないです。)

3.ファン

noctuaのファンが秀逸なのは間違いありません。ラジエータに付ける場合を除き、ケースファンは風量を重視するのが一般です。

型式 回転数 ノイズ 風量[m3/h] 風圧[mmH2O] 羽数
NF-A20 PWM 800 18.1 146.9 1.08
NF-P14s redux-1200 PWM 1200 19.6 110.3 1.29 9枚羽
NF-A14 PWM 1500
1200*1
24.6
19.2*1
140.2
115.5*1
2.08
1.51*1
7枚羽
NF-P12 redux-1300 PWM 1300 19.8 92.3 1.68 9枚羽
NF-S12B redux-1200 PWM 1200 18.1 100.6 1.31 7枚羽

1 with Low-Noise-Adaptor

続いてthermaltakeです。

型式 回転数 ノイズ 風量[m3/h] 風圧[mmH2O] 羽数
Riing Trio 20 RGB Case Fan TT PremiumEdition 1000 28 209.7 1.7 11枚羽
Riing Plus 20 RGB Case Fan TT Premium Edition 1000 29.2 200.3 1.68 11枚羽
TOUGHFAN 14 High Static Pressure Radiator Fan 2000
1300*2
33.2
25.2*2
202.2 3.54 9枚羽

2 with Low-Noise Cable

続いてSilverStoneです。

型式 回転数 ノイズ 風量[m3/h] 風圧[mmH2O]
Air Penetrator 140i ARGB 2000 41.3 124.75 2.72
Air Penetrator 120i PRO 2000 38.9 125.6 2.52
Air Penetrator 120i 1350 18 77.8 1.08


疲れたので、次回更新します。

EMAベースのZigZagの書き方

1.きっかけ

 EMAベースのZigZagってあんま見ないんで作ってみようかなっていうか,前に作ったんだけどどのパソコンに入ってるっけっていう状態

2.そもそもZigZagってどうやってるっけ

 高値,安値を探してジグザグにする感じ。最低算出期間とかもろもろ決められる。ダウ理論っぽいのが視覚化できる。

3.EMAべースにするとどうなる?

 こんなんなると思います。
 f:id:iinebot:20201112124519p:plain

4.実装

 実装するにあたり一番大事なことは,もとのZigZagのコードを見ないことです。
 なぜなら,元のコードを見ると,それを理解するところから始めなくてはいけません。
 コードの読み解く力は育まれる可能性が高いですが,ぼくには合ってません。
 自分でまず書いてみて,うまくいかなかったら見て参考にするくらいが良いと思います。
 あんまりちゃんとしてないけど・・・。

//+------------------------------------------------------------------+
//|                                                    ZigZagEMA.mq4 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 6
#property indicator_color2 clrBlack
#property indicator_type2 DRAW_LINE
#property indicator_color3 clrCyan
#property indicator_type3 DRAW_LINE
#property indicator_color4 clrMagenta
#property indicator_color5 clrBlue
#property indicator_color6 clrRed

// 設定項目
input string dummy1 = "---------------------";//MAの期間
input int   MAband = 25;//MAの期間
input ENUM_MA_METHOD MA_Method1  = MODE_EMA;  //移動平均の種類

double maValue[];
double zigZagValue[];
double zigZagHighValue[];
double zigZagLowValue[];
double lowbuf[];
double highbuf[];

bool highTrend = false;
bool lowTrend = false;
bool highMode = false;
bool lowMode = false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   IndicatorBuffers(6);

   SetIndexBuffer(0, maValue);

   SetIndexBuffer(1, zigZagValue);
   SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2,Magenta);

   SetIndexBuffer(2, zigZagHighValue);
   SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,3,clrAqua);

   SetIndexBuffer(3, zigZagLowValue);
   SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,3,clrYellow);

   SetIndexBuffer(4, highbuf);
   SetIndexBuffer(5, lowbuf);
//
//   SetIndexStyle(4,DRAW_ARROW,STYLE_SOLID,5,Blue);
//   SetIndexArrow(4,233);
//
//   SetIndexStyle(5,DRAW_ARROW,STYLE_SOLID,5,Red);
//   SetIndexArrow(5,234);
//SetIndexEmptyValue(0,0.0);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

   int limit;

   int i = 0;
   int counted_bars=IndicatorCounted();
   if(counted_bars<0)
      return(-1);
   limit=Bars-counted_bars-1;

   int counter = 0;
   int hPosition,lPosition;
   double hValue,lValue;
   for(i = 0 ; i < limit  ; i++)
     {
      lowbuf[i] = EMPTY_VALUE;
      highbuf[i] = EMPTY_VALUE;
      zigZagValue[ i ] = EMPTY_VALUE;
      zigZagHighValue[ i ] = EMPTY_VALUE;
      zigZagLowValue[ i ] = EMPTY_VALUE;
      maValue[i] = 0.0;                  // インジケータ1に算出結果を設定
     }
   for(i = 0 ; i < limit  ; i++)
     {
      maValue[i] = iMA(
                      NULL,            // 通貨ペア
                      0,               // 時間軸
                      MAband,          // MAの平均期間
                      0,               // MAシフト
                      MA_Method1,      // MAの平均化メソッド
                      PRICE_CLOSE,     // 適用価格
                      i                // シフト
                   );
      zigZagValue[ i ]  =  maValue[i];

     }

   highTrend = true;

   for(i = limit - 1  ; i >= 0  ; i--)
     {
      if(zigZagValue[i + 1] <= zigZagValue[i])//upper trend
        {
         if(lowMode)//down trend からやってきた
           {
            zigZagHighValue[i] = zigZagValue[i];
           }
         lowMode = false;
         highMode = true;


        }

      else
         if(zigZagValue[i + 1] > zigZagValue[i])//down trend
           {
            if(highMode) //upper trendからやってきた
              {
               //lowbuf[i] = zigZagValue[i];

               zigZagHighValue[i] = zigZagValue[i];

              }
            lowMode = true;
            highMode = false;

           }


     }
     
     zigZagHighValue[0] = maValue[0];

//補完作業

   int count,j;
   count = 0;
   double a,b;
   for(i = limit - 1  ; i >= 0  ; i--)
     {
      if(zigZagHighValue[i] == EMPTY_VALUE)
        {
         count += 1;

        }
      else
        {
         if(count ==0)
           {
            lowbuf[i] =zigZagHighValue[i];
           }
         else
           {
            a = (zigZagHighValue[i + count + 1] -zigZagHighValue[i]) / count;
            b = zigZagHighValue[i]  - i * a;
            for(j = i; j <= i+count; j++)
              {
               lowbuf[j] = a * j + b;
              }
            count = 0;
            i += 1;

           }
        }

     }


//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {

  }//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

//---

//+------------------------------------------------------------------+

Windowsで共有フォルダにアクセスできないときの対処方法(備忘)

原因

1.そもそも共有されてない
2.権限設定がない
3.ファイアウォールが設定されてない(←今回ここ)

1とか2はネットで見なくてもできるんだけど,3ってなかなか書かれてるところが無かったので,備忘録としてまとめることに。

今までは,ファイアウォール切っちゃえって無効にしてたけど,このご時世なにがあるかわからないので・・・。

対処方法

 管理者権限でコマンドプロンプトを開き,

netsh advfirewall firewall set rule name="Netlogon サービス (NP 受信)" new profile=private enable=yes

を実行する。
こんなことしなくても,ファイアウォールの設定画面開いてから,【ファイアウォールを介したプログラムまたは機能を許可する】を開いて,Netlogon サービス ってのにチェック入れてあげればいいんだけど,リモートでアクセスしてるとGUIが使いにくいので。

(LINE NotifyとMQL4を使って)MQLからライン通知

ここを参考に・・・というかほぼそのまま!
https://gist.github.com/syusuke9999/feebe00f4ddf5b40459d28a24f0a33ab

bool SendLine(string message,string token){
   char message_data[], result[];
   string   RequestMethod     =  "POST";
   string   headers           =  "Content-Type: application/x-www-form-urlencoded" + "\r\n";
            headers           += "Authorization: Bearer " + token + "\r\n";
   int      timeout           =  10000;
   string   result_headers    =  NULL;
   string   message_text      = "message=";
            message_text      += message;
   StringToCharArray(message_text,message_data,0, StringLen(message_text));
   
   int res = WebRequest(RequestMethod, END_POINT_URL, headers, timeout, message_data, result, result_headers);
   if(res==-1)
   {
      Print("Error in WebRequest. Error code  =",GetLastError());
      return false;
   }
   else
   {
      string result_text = StringConcatenate(CharArrayToString(result,0,ArraySize(result)));
      int replaced = StringReplace(result_text,"\"","");
   }
   return true;
}

あとtokenとったりなんなりは、Qiitaとかがわかりやすですね!
qiita.com


オプションのエキスパートアドバイザにhttps://notify-api.line.me/api/notifyを忘れないでください!
f:id:iinebot:20200730085330p:plain

AngleSharpで画像スクレイピング

まずは,この辺を一読します.

HttpClientをusingで囲わないでください - Qiita

【C#】AngleSharpの使い方メモ - Qiita

AngleSharpでスクレイピングする - Qiita

C#でモダンにスクレイピングするならAngleSharp - Qiita

背景

 ある方のブログをよく見ているのですが,印刷した際に画像が小さく,ちょっと見にくくなってます・・・.
 そこで,HTMLを解析して,画像だけ頂いちゃおうっていうのが今回の狙いです.

開発環境

 Windows7(サポート切れごめんなさい)
 VisualStudio2019 16.5.4
 .net Framework 4.7.2

まずはNuGet

 まずはNuGetでAngleSharpを落としてきます.
f:id:iinebot:20200602085154p:plain

さっそくコード!

 んで,書いていきますが,HttpClientをusingで囲わないでください - Qiitaのとおり,メンバーにHttpClientを宣言します.
 批判しているわけではないですが,他のQiita記事はusingしてます.
 実は,ある方のブログ専用で作ってる関係で,記事ごとのタイトルと記事ごとのURLが取得済みなので,その前提で話が進みます・・・.

メンバー
        static WebProxy proxy = new WebProxy(@"proxyserver.co.jp:portNO"); //必要であれば
        static HttpClientHandler handler = new HttpClientHandler()
        {
            Proxy = proxy,
        };
        // HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
        static readonly HttpClient client = new HttpClient(handler);
        public Form1()
        {
            InitializeComponent();
        }
スクレイピング
        private async System.Threading.Tasks.Task scrapper(string urlstring, string folder)
        {
            var doc = default(IHtmlDocument);

            using (var stream = await client.GetStreamAsync(new Uri(urlstring)))
            {
                HtmlParser parser = new HtmlParser(); //htmlパーサーにぶっこむ
                doc = await parser.ParseDocumentAsync(stream);
            }

            var imgTag = doc.QuerySelectorAll("img");// HTMLからimgタグの値を取得する
            foreach (IHtmlImageElement n in imgTag)
            {
                string uri = n.Source;
                string[] parser = { "?" };
                if ((uri.Contains("png") || uri.Contains("jpg")) && uri.Contains("落としたいブログのユーザ名"))
                {
                    Debug.WriteLine(uri.Split(parser, StringSplitOptions.RemoveEmptyEntries)[0]);
                    FileDownload(uri.Split(parser, StringSplitOptions.RemoveEmptyEntries)[0], folder);
                }
            }
        }
ファイルダウンロード部
        private void FileDownload(string url, string folder)
        {
            try
            {
                string path = System.IO.Directory.GetCurrentDirectory() + "\\" + folder;
                if (!Directory.Exists(path))
                {
                    System.IO.DirectoryInfo di = System.IO.Directory.CreateDirectory(path);
                }
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                req.UserAgent = "Chromeなどのブラウザのユーザエージェント";
                req.Proxy = proxy;
                string[] sep = { "/" };
                string[] fileName = url.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                WebResponse res = req.GetResponse();
                using (Stream st = res.GetResponseStream())
                {
                    using (FileStream fs = new FileStream(path +"\\" + fileName.Last(), FileMode.Create))
                    {
                        st.CopyTo(fs); //ストリームのコピー(.NET Framework 4以降)
                    }
                }
            }
            catch (WebException exc)
            {

            }
        }
ボタンクリック部
        private async void button1_ClickAsync(object sender, EventArgs e)
        {
            //TextBoxに入力するフォーマットは URL,フォルダ名 です.
            StringReader rs = new System.IO.StringReader(textBox1.Text);//StringReaderにテキストボックスをぶっこむ
                        
            while (rs.Peek() > -1)//1行ずつ読み込んで
            {
                string[] sep = { "," };
                string[] paths = rs.ReadLine().ToString().Split(sep, StringSplitOptions.RemoveEmptyEntries);//カンマで分ける
                await scrapper(paths[0],paths[1]);
            }
            Debug.WriteLine("END");
        }

実行結果

こんな感じで,実行ファイルと同じフォルダに格納できました!
f:id:iinebot:20200602101436p:plain

Metalを始める

以下を翻訳しました。DeepLで・・・。

www.raywenderlich.com

"In iOS 8, Apple released its own API for GPU-accelerated 3D graphics: Metal."

iOS 8では、AppleGPUで加速された3Dグラフィックスのための独自のAPIを公開しました。Metalです。

"Metal is similar to OpenGL ES in that it’s a low-level API for interacting with 3D graphics hardware."

Metalは、3Dグラフィックスハードウェアと対話するための低レベルAPIであるという点で、OpenGL ESに似ています。

"The difference is that Metal is not cross-platform. Instead, it’s designed to be extremely efficient with Apple hardware, offering improved speed and low overhead compared to using OpenGL ES."

違いは、Metalはクロスプラットフォームではないということです。その代わりに、Appleのハードウェアで非常に効率的に動作するように設計されており、OpenGL ESを使用する場合と比較して、速度が向上し、オーバーヘッドが低くなっています。

続きを読む

Twitter Developerに登録してみる(2020/3/5現在)

このあたりを参考に
dev.classmethod.jp

1.きっかけ

 ツイッターには ちんちん とツイートすると,リツイートしてくれるBOTがあります。
f:id:iinebot:20200305111513p:plain

ほかにも,カピバラを指摘してくれたり,楽しいです。こういったのを作るには,既にあるツイッターと連携したサービスを使うか,自前で実装するしかありません。
これからいろいろな用途を考えるとデベロッパー登録しちゃったほうがいいかなと思ったので,それを残します。

ちなみに,自動いいねや自動リツイートのサービスは,ぼくが調べた限りフリーで使えるものはありませんでした。

2.登録手順

 開発者用のアカウントを新規に作って登録してみます。また,電話番号認証が済んでいないと登録できないようなので,新規に作ったアカウントには,電話番号認証を済ませておきます。text plusというアプリを利用すると,SMS用の番号がもらます。某レジユキさんによると,出会い系のアプリなんかも電話番号認証が多いようなので,悪用しないでください・・・。

開発者申請したいアカウントで

Developer

にアクセスします。右上の[ Apply ]を選択します。
f:id:iinebot:20200305112646p:plain

[Apply for a developer account]をクリックします。
f:id:iinebot:20200305112616p:plain

使用用途を選べってことなんだと思います。
趣味の世界なので,そういうのを選ぼうと思うので,今回は,[Making Bot]を選択します。
選んだら右下の[Next]を選択します。
f:id:iinebot:20200305112848p:plain

次に色々聞かれるので書きます。そしたら[Next]って押します。
f:id:iinebot:20200305113251p:plain

ここからが大変です・・・。
f:id:iinebot:20200305113638p:plain
英語で入力しないといけません。
Google先生にすべて頼ることにします。

[In your words]にはこうやっていれました。
f:id:iinebot:20200305114539p:plain

データ分析しないのでNo!!
f:id:iinebot:20200305114724p:plain

リツイートしたいのでYes!!
f:id:iinebot:20200305114740p:plain

データは公開しないのでNo!!
f:id:iinebot:20200305114832p:plain

政府機関じゃないのでNO!!
f:id:iinebot:20200305114849p:plain

入れたあとに[Next]するとこれでいいか?的な感じで聞かれるので,
よければ[Good]って書いてるほうを選択する。
f:id:iinebot:20200305115305p:plain

利用規約みたいです。チェックつけて[Submit Application]を選択します!
f:id:iinebot:20200305115356p:plain

申請完了です!申請完了の旨のメールもきます!
f:id:iinebot:20200305115441p:plain

審査受かるのでしょうか?
(ง `▽´)╯ハッハー!!

Excelのシート保護やブック保護のパスワードを忘れた場合の対処方法

シート保護やブック保護したあとにパスワードを忘れてしまったことはありませんか。
Office 2007以降ですが,パスワードを無理矢理解除する方法があります。

Office 2007以降でExcelやWordではOffice Open XMLというものが採用されています。
詳しくは以下から
Office Open XML - Wikipedia

拡張子が.xlsxという最後にxやmがついたものはこの形式ファイルになります。
もともとがzipファイルなので,拡張子をzipに変更すればある程度見れるようになります。

まず,拡張子を変更します。
f:id:iinebot:20200305093517p:plain
f:id:iinebot:20200305093539p:plain

後ろに.zipを付けます。
f:id:iinebot:20200305093549p:plain

当方の環境はWindows 7ですので,このままダブルクリックします。
f:id:iinebot:20200305093600p:plain
f:id:iinebot:20200305093622p:plain
f:id:iinebot:20200305093747p:plain

シートの保護を解除したいシート名.xmlを右クリックしてコピーします。
f:id:iinebot:20200305093833p:plain

適当な別のフォルダに貼り付けします。

そのファイルをメモ帳か何かで開いて

<sheetProtection ・・・・・・>  

の部分を削除します。
f:id:iinebot:20200305093904p:plain

↓削除後
f:id:iinebot:20200305093914p:plain

このxmlを上書きしてエディタを閉じます。

あとは逆手順で,出来上がったxmlファイルをコピーして
貼り付けします。(上書きするかどうかの警告メッセージが出ますが無視してOK)
f:id:iinebot:20200305093951p:plain

あとは,後ろの.zipを消して
f:id:iinebot:20200305094011p:plain
元に戻すだけ。
f:id:iinebot:20200305094017p:plain

ブック保護を解除する場合は,
f:id:iinebot:20200305094056p:plain
のworkbook.xmlをどこか適当なとこにコピーしてメモ帳か何かで開き

 <workbookProtection ・・・>   

を消せばOKです。

ただ,上記方法は間違うとファイルが開けなくなる恐れがありますので,バックアップの上実施してください。あと,自己責任でお願いします。。。。