TechnologyMemo

その他メモ

C#

async, awatについて

  • あるメソッドにてawaitを用いたい場合、そのメソッドをasyncとする
  • asyncを付与したメソッドの返り値はvoid, Task, Task<T>とする(C# 7.0以降では例外あるみたいだけど自分は使わなそう)
  • asyncは単に装飾として付けられ、動作自体は普通のメソッドと変わらないみたい

  • awaitはTaskクラスの前に付与することができる
  • あるメソッド(例としてfuncAとする)内でawaitにてTaskの終了を待つと、処理はfuncAを呼び出したメソッドのもとへと戻る。 そしてTaskが終了したタイミングで再びfuncAに処理が戻る。
  • awaitにてTask<T>の処理の終了を非同期的に待った場合、その返り値のTを受け取ることができる。

コード例

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

class Program
{
    //何らかの重い処理
    static int SomeHeavyFunc(int i)
    {
        Thread.Sleep(5000); // 何か重い処理をする
        return i;
    }

    //非同期処理の例
    static async Task Sample() {
        Console.WriteLine("{0:0000}ms : 1. Sampleメソッド開始", timer.ElapsedMilliseconds);
        Thread.Sleep(1000);

        Console.WriteLine("{0:0000}ms : 2. 同期的にSomeHeavyFunc実行", timer.ElapsedMilliseconds);
        Program.SomeHeavyFunc(1);

        Console.WriteLine("{0:0000}ms : 3. 非同期的にSomeHeavyFuncの終了を待つ", timer.ElapsedMilliseconds);
        await Task.Run(
            () => {Program.SomeHeavyFunc(2);}
        );

        Console.WriteLine("{0:0000}ms : 4. Sampleメソッド終了", timer.ElapsedMilliseconds);
    }

    static Stopwatch timer;

    static void Main() {
        //時間計測開始
        timer = new Stopwatch();
        timer.Start();

        Console.WriteLine("{0:0000}ms : 5. メインメソッド開始", timer.ElapsedMilliseconds);
        Task t = Program.Sample();

        Console.WriteLine("{0:0000}ms : 6. 処理がメインメソッドに戻る", timer.ElapsedMilliseconds);

        //GUIやASP.NETの場合は、コンテキストの処理の関係で、awaitを行うタスクに対して
        //Task.Waitを行うとデッドロックになってしまう。
        //(awaitにて元のスレッドに戻ろうとするも、元のスレッドがタスク終わるのを待っているので、
        //互いに処理が終わるのを待つような感じになるみたい)

        //CUIではコンテキストの処理の関係でWaitしてもデッドロックにならず、
        //Mainメソッドではawait出来ないので、例外的にTaskに対してWaitを行ってもよいらしい。
        //Waitを使うのはCUIのMainメソッドだけにして、GUIではawaitで処理の終わりを待のがよさそう。
        //C#7.1で、async Main methodが追加されて、CUIでもGUIと同じような記述で行けるようになったみたい
        t.Wait();

        Console.WriteLine("{0:0000}ms : 7. メインメソッド終了", timer.ElapsedMilliseconds);
    }
}

このコードを実行すると、次の順で処理が行われる

経過時間 実行される処理 解説
0ms 5.メインメソッド開始 処理の開始
0ms 1.Sampleメソッド開始 この時点ではまだ同期処理
1000ms 2.同期的にSomeHeavyFunc実行 この時点ではまだ同期処理なので、Sample内で1秒待ったのちにSomeHeavyFuncが呼び出される
6000ms 3.非同期的にSomeHeavyFuncの終了を待つ このタイミングで非同期に。SampleはSomeHeavyFuncの終了待ちになり、処理はメインメソッドへ戻る。
6000ms 6.処理がメインメソッドに戻る Sampleの実行と非同期でメインメソッドの処理が実行される
11000ms 4.Sampleメソッド終了 Sampleメソッドの終了待ちをメインメソッドで行ったので、先にSampleメソッドが終了する
11000ms 7.メインメソッド終了 メインメソッドも終了する。ちなみにSampleタスクのwaitをしないと、メインメソッドが先に終わるので4の出力はされない。

デッドロック周りの参考 https://msdn.microsoft.com/ja-jp/magazine/jj991977.aspx

デフォルトで付属のコンパイラ

.NET Frameworkはvista以降のosに標準でインストールされており、それにC#のコンパイラも付属してるので、 特に何もインストールせずともC#はコンパイルできる。

「C:WindowsMicrosoft.NETFramework」か、「C:WindowsMicrosoft.NETFramework64」の下にバージョンごとに.NETがあるので、 その配下の「csc.exe」がコンパイラ

以下みたいに使うとカレントディレクトリ下に実行ファイルができる

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe src.cs

SQLite

制約の変更について

SQLiteのALTER TABLEにて可能な操作は、カラムの追加とテーブル名の変更のみ

他の操作(列の削除とか制約の変更とか)をしたいときは、 テーブルを作り直してINSERT SELECTする

参考 https://www.sqlite.org/lang_altertable.html

型について

データ型としては以下のものがある

  • NULL
  • INTEGER
  • REAL
  • TEXT
  • BLOB

また、列には「型の類似性(type affinity)」というものを指定できる。 値を保存する際に、列に指定した「型の類似性」に従い、値を変換する(変換できない場合はそのまま値を保存する)。

なので列の型の類似性にINTEGERを指定したのに、それにTEXTを保存できたりする。
最大長などは持てないので、VARCHARA(10)としたカラムに10文字以上保存できたりもする。
テーブル作成の際に指定した型から、型の類似性を判断する(列の型にCHARという文字が含まれていたらTEXTなど)。
列に指定できる「型の類似性」には以下のものがある。
  • TEXT
  • NUMERIC
  • INTEGER
  • REAL
  • NONE

参考 https://code-examples.net/ja/docs/sqlite/datatype3

参考 https://blog.ohgaki.net/sqlite-data-type-specification

Linuxパーミッション

各パーミッションの意味

権限 ファイル ディレクトリ
“r”読み(4) ファイルの内容を表示 ディレクトリ内のリスト表示
“w”書き(2) ファイルの上書き、変更 ディレクトリ内にファイル作成、削除
“x”実行(1) 実行ファイルの実行 そのディレクトリに移動

ディレクトリのx権限は、その配下のディレクトリにも及ぶので注意(上のディレクトリに移動できないから、その下のディレクトリにアクセスできない)。

そのほかの権限については、親ディレクトリだけ見ればおk。

権限変更のコマンド例

$ chmod 775 testfile

# ディレクトリ含め再帰的に変更
$ chmod -R 755 dir

# rwxにて権限指定の例。 実行権限を付与
$ chmod +x myscript
# 読み込みと実行のみに設定
$ chmod =rx myscript

# 対象を指定した上でrwxにて権限指定の例 (uはユーザ、gはグループ、oはその他)
# グループとその他から実行権限を剥奪
$ chmod go-x myscript

備考 所有者変更の例

# chown [オプション] ユーザー[:グループ] 対象ファイル
$ chown user:group testfile
# ディレクトリ以下も再帰的に修正
$ chown -R user testdir

参考 http://www.infraeye.com/study/linuxz26.html

スライム君

スライム君のフォントは以下のリポジトリにて管理されている。

https://github.com/googlei18n/noto-emoji/

2015-09-29と、2017-03-10にリリースされたフォントにスライム君の絵文字が含まれている。

2015-09-29例 srm_1_1 srm_1_2 srm_1_3
2017-03-10例 srm_2_1 srm_2_2 srm_2_3
2015-09-29のフォントだと
emoji_u1f60a ~ emoji_u1f62f
emoji_u1f64b ~ emoji_u1f64f
emoji_u1f466 ~ emoji_u1f491
emoji_u1f600 ~ emoji_u1f647
あたりがスライム君。

2017-03-10のフォントだと
emoji_u1f60a ~ emoji_u1f62f
emoji_u1f600 ~ emoji_u1f644
emoji_u1f910 ~ emoji_u1f925
あたりがスライム君。

Eel

Eelにて新規ウィンドウをアプリケーションモードで開きたい

htmlから開くとアプリケーションモードが解除されるのでPythonから開く。アプリケーションモードで動作させなくてもよいなら素直にhtmlから開いた方がいいと思う。

以下のようにすれば、open_window関数を呼んだ際に新規ウィンドウがアプリケーションモードで開かれる。

import eel

def main():
    eel.init("web")
    eel.start("main.html")

"""新しいウィンドウを開く"""
@eel.expose
def open_window():
    eel.start("main.html")

if __name__ == '__main__':
     main()

エラーメッセージが出て気持ちが悪い場合は以下のようにする

import eel

web_app_options = {
    'port': 0,
}

def main():
    eel.init("web")
    # eel.start()では、引数に渡したオプションに未指定のものがあった場合、デフォルトの値を詰めてくれる。
    eel.start("main.html", options=web_app_options)

"""新しいウィンドウを開く"""
@eel.expose
def open_window():
    # 第一引数は開きたいURLのリスト、第二引数はeel.start()に渡したオプション
    eel.browsers.open(["main.html",], web_app_options)

if __name__ == '__main__':
     main()

参考 https://blog.nktk-tech.com/2018-10-04-01/

あるベクトル同士の回転角を求めたい

参考 http://www5d.biglobe.ne.jp/~noocyte/Programming/Geometry/RotationDirection.html

WindowsシンボリックリンクのExplorerによる操作

シンボリックリンクは以下のように作成する(管理者としてプロンプトを実行しなければならない)

mklink /D [リンク] [ターゲット]

作成したシンボリックリンクをExplorerから操作したところ、以下のような動作になった。(ディレクトリに対するシンボリックリンクの場合)

・Explorerでシンボリックリンクをコピーした場合は、シンボリックリンクはただのフォルダとして、その参照先までコピーされる。

・Explorerでシンボリックリンクを含むフォルダをコピーした場合は、シンボリックリンクは空フォルダとしてコピーされる。

・Explorerでシンボリックリンクを削除した場合は、シンボリックリンクの参照先には影響しない。

・Explorerでシンボリックリンクを含むフォルダを削除した場合は、シンボリックリンクの参照先には影響しない。

Beautiful Soup

あるタグの配下のhtmlをそのまま出力したい

あるタグ配下の文字列を取得したい場合は、.stringを用いて以下のように書ける。

例 :

from bs4 import BeautifulSoup

html = "<div>test</div>"
soup = BeautifulSoup(html, "html.parser")
print(soup.find("div").string)

出力結果

test
ただし、取得したタグ配下に、さらにほかのタグがあると.stringプロパティはNoneを返す。
そのような場合は、
1. .textプロパティを用いる(配下のタグはすべて削除される)
2. str関数で文字列に変換する(自身のタグも出力される)
3. .contentsにて、配下のタグを全て取得し文字列に変換する(自身のタグは出力されない)
などが考えられると思う。

例 :

from bs4 import BeautifulSoup

html = "<div>test <br>hoge1 <div><div>hoge2</div></div> <br>hoge3</div>"
soup = BeautifulSoup(html, "html.parser")
first_div = soup.find("div")

print("0 : " + str(first_div.string))
print("1 : " + first_div.text)
print("2 : " + str(first_div))
print("3 : " + "".join(map(str, first_div.contents)))

出力結果

0 : None
1 : test hoge1 hoge2 hoge3
2 : <div>test <br/>hoge1 <div><div>hoge2</div></div> <br/>hoge3</div>
3 : test <br/>hoge1 <div><div>hoge2</div></div> <br/>hoge3

3に関してはもう少しスマートなやり方がありそうな気がする。

参考 : http://kondou.com/BS4/#string

WordPressにて絵文字を入力する

普通に入力すればよい。
Windows10の場合ソフトウェアキーボードが使える。

物理ベースレンダリング用語ざっくりメモ

反射性

■拡散光 : diffusion : diffuse
物質内に光が入り、乱反射して入射角とは関係ない方向へ行く光。
反射光と違い、拡散光は個所により色が変わらないとして計算することが多い(明度は変わる)。

■反射光 : reflection : specular
そのまま。入射角の反対へ行く光

エネルギー保存の法則により、反射光と拡散光の和は、入射した光より強くならない。
金属のように反射しやすい物質の場合、拡散光は少なくなる。
-> 金属のように反射しやすい物質は、反射光が当たらない個所が暗くなる
あまり反射しない物質だと、反射光がない箇所でもそれなりに明るく見える。
ソフトによってはmetalnessといったパラメータで調整する

マイクロサーフェス

上記の項目は表面の粗さとはまた別。
表面が粗い場合、反射光の向きがバラバラになる。
-> 表面が荒い方がハイライトが広くなり、エネルギー保存の法則よりハイライトは暗くなる。
roughnessやらgloss、smoothnessといったパラメータで調整することが多い

フレネル反射

入射角が広い方が反射しやすい

GIとIBL

GIは大局照明のことで、ほかのオブジェクトからの反射光とかを考慮してレンダリングを行うこと。
IBLはイメージベースドライティングの略で、360度画像を用いてレンダリングを行うこと。

ガンマ補正

線形のデータをそのままディスプレイ表示すると、逆ガンマ補正がかかって若干暗く見える。
レンダリングするときにガンマ補正を掛けて、元データより大きい明るさのデータにする。
-> 画面の表示が線形になる。
ペイントソフトなどで描いたテクスチャは、結果的にガンマ補正がかかったデータになるので、
それを読み込む際に逆ガンマ補正を掛けてリニアに直す。
(人間の感覚で明るさを決めているが、内部的には逆ガンマ補正がかかっているので、
それを感覚でガンマ補正を掛けているような感じだと思う)
-> 出力の際に再度ガンマ補正をかける。