クリーンルームに持ち込めるキャリーバッグ
エレファインで入手可 台湾製 W42cm x H32cm x D6cm \1,980
http://www.elefine.jp/SHOP/BAGCLBK60.html
完全ビニール製のバッグ
http://www.komonoya.com/s_etc1.html
Amazon
http://goo.gl/IVp6t
エレファインで入手可 台湾製 W42cm x H32cm x D6cm \1,980
http://www.elefine.jp/SHOP/BAGCLBK60.html
完全ビニール製のバッグ
http://www.komonoya.com/s_etc1.html
Amazon
http://goo.gl/IVp6t
UI Automationについて参考になりそうなページを50個ほどブックマークしたものの、多すぎるので入口として役立ちそうなページを抜粋しておく。
本来はUIテストやアクセシビリティを目的としているようだが、今回は他人が作ったソフトを自動制御するために使う。
プロバイダとクライアントの説明があるが、今回はクライアントのことが分かればよいはず。
Windows Forms、WPF、サードパーティのUIコンポーネントでもたいていはオートメーションプロバイダとして扱えるようだ。
確証はないがUISpy.exeを使ってAutomationIdなどが確認できれば対応していると思っていいのではないかと思っている。
UI Automation Client Programmer’s Guide (Windows)
Bugslayer – こちらGUIコントロール、トム少佐応答せよ
UIツリーを辿り、プロパティを確認するにはUISpyやInspect Objectというのがある。
UI Spy(UISpy.exe)が含まれているWindows SDK Version
現状はC#でやるのが無難そうだ。
TclでもGarudaを使うと、インプロセスで.NET Frameworkのクラスを利用できるのだが、まだ未完成、ドキュメントがないに等しいので難しい。クラスメソッドやイテレーションを使えるのかすら分からない。
COMは茨の道だと思われるのでできれば避けたい。
ちまちまUI Treeを歩き回るコードを書く代わりに、もっと楽にしてくれるライブラリというのもあるみたいだ。
White
White Tutorial
StackOverflow White – File Open Dialog Box
White – Working with window
UISpyみたいなインターフェースと、UI Automationプロバイダとして必要な機能を持っているかチェックするためのソフト。
Visual UI Automation Verify
UIVerifyが内部で使っているライブラリがこれ。
UI Automation COM-to-.NET Adapter
.NET版のAPIがあるのに何でラッパーを作る必要があるのかは気になるが、まだ調べてない。
SXGAのリモートデスクトップウィンドウをアスペクト比を保ちつつ65%に縮小し、FullHDのディスプレイの右下に配置したい。手計算でも簡単にできることだが、今まで使ってなかった行列計算ライブラリの練習台に使うことを思いついた。
+-----------------------------+ | | | | | | | | | | | nw------------+ | |xxxx | | | x rec x | | | xxxx | | | xxx +---------------+------------se
package require math::linearalgebra namespace eval LinearAlgebraSample { namespace import -force ::math::linearalgebra::* set scale 0.65 set v(se) [mkVector 2] set v(rec) [mkVector 2] setelem v(se) 0 0 1920 setelem v(se) 1 0 1280 setelem v(rec) 0 0 1280 setelem v(rec) 1 0 1024 set v(nw) [sub_vect $v(se) [scale $scale $v(rec)]] show $v(nw) } |
例題がしょぼすぎて練習になってないな。
線形代数苦手でプログラミングにも活用してないし、Maxima、Scilab、Octave、Rとかも使ってない。
ロボットの研究室にいたのに行列計算が苦手というのは勉強してなかった証拠ですね。
Prerequisites
Build tool = MinGW GCC v4.7.2
Tcl build path = /c/src/tcl8.6.0/win
Tcl install path = /c/bin/tcl8.6.0
SQLite3 build path = /c/src/sqlite-autoconf-3071300/tea
wxSQLite3 secure source path = /c/src/wxsqlite3-3.0.2/sqlite3/secure/src
Tcl
./configure –enable-threads –prefix=(Tcl install path)
make
make install
Tk
./configure –enable-threads –with-tcl=(Tcl build path)
make
make install
TclSQLite
Copy the files in (wxSQLite3 secure source path) to (SQLite3 build path)/generic.
Open tclsqlite3.c and replace “sqlite3.c” by “sqlite3secure.c” in the line #4.
./configure –enable-threads –with-tcl=(Tcl build path) CFLAGS=”DSQLITE_HAS_CODEC”
make
make install
This also works with ActiveTcl.
NAT (Network Address Translation)
グローバルIPとローカルIPを1:1対応させる。
NAPT (Network Address Port Translation)
グローバルIPアドレスとポート番号のペアをローカルIPとポート番号のペアに1:1対応させる。
NAPTには多数の同義語が存在する
静的NAT、静的NAPTは外部から内部のネットワークへのアクセスに使う。一般的なブロードバンドルータの設定に存在するのはこれらの設定。
動的NAT、動的NAPTは内部から外部への通信に対する応答が、送信元に返るようにするための機能であり、通常ユーザーが意識することはない。
と思う。
参考
IPマスカレード(NAPT,PAT,NAT+)を設定する
NAT と IPマスカレード(ポートフォワーディング) について
4.インターネットへの接続形態
Excel2007登場以来、なんかいい方法はないものかと探していたけど、ついに見つけた。ありがたや。
Public Sub main() On Error GoTo L_Exit With Selection.ShapeRange.Nodes On Error Resume Next Dim i As Integer For i = 1 To .Count .SetSegmentType i, msoSegmentLine .SetEditingType i, msoEditingCorner Next End With L_Exit: On Error GoTo 0 End Sub |
林檎の木で紹介されてたCloverを入れてみたけど、マウスホイールでスクロールすると無限ループに陥ってしまった。かざぐるマウスを停止すると問題は発生しない。設定でエクスプローラを除外するとか、いろいろやってみたけど効果はなし。
今まで使ったマウスジェスチャソフトで一番気に入っているものだけど、Tcl/Tkとの相性問題というのもあった。
最近はブラウザを使い分けることがほぼなくなったことと、Gestures for Chromeがそろそろ完成度が高まってるのではないかと思い、
ちょっと入れてみました。かざぐるマウスの自分設定と同じにしたものを晒しておきます。
Chrome拡張はchrome:chrome_urlsに対しては無効なので、スタートページでもやはり無効です。
あとページによってはジェスチャの開始点が限定される場合がある。それ以外はそこそこ使えそうなので、しばらくこれで試してみます。
{ "name": "Chrome Gestures", "version": "1.12.1", "normal_actions": { "L": { "name": "back", "args": [] }, "R": { "name": "forward", "args": [] }, "UL": { "name": "select left tab", "args": [] }, "D": { "name": "go to #1", "args": [ "http://www.google.com/", "Google" ] }, "DR": { "name": "close this tab", "args": [] }, "#FlipBack": { "name": "back", "args": [] }, "#FlipForward": { "name": "forward", "args": [] }, "U": { "name": "run script #1", "args": [ "(function(){if((document.fullScreenElement&&document.fullScreenElement!==null)||(!document.mozFullScreen&&!document.webkitIsFullScreen)){if(document.documentElement.requestFullScreen){document.documentElement.requestFullScreen();}else if(document.documentElement.mozRequestFullScreen){document.documentElement.mozRequestFullScreen();}else if(document.documentElement.webkitRequestFullScreen){document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);}}else{if(document.cancelFullScreen){document.cancelFullScreen();}else if(document.mozCancelFullScreen){document.mozCancelFullScreen();}else if(document.webkitCancelFullScreen){document.webkitCancelFullScreen();}}})()", "Fullscreen" ] }, "UR": { "name": "select right tab", "args": [] }, "DL": { "name": "re-open closed tab", "args": [] } }, "linkdrag_actions": { "D": { "name": "open in new tab", "args": [] }, "DU": { "name": "open in background tab", "args": [] }, "U": { "name": "copy url", "args": [] }, "UD": { "name": "copy url and text", "args": [] } }, "textdrag_actions": { "DR": { "name": "search with #1 in new tab", "args": [ "http://www.google.com/search?q=%s", "Google" ] }, "UL": { "name": "copy text", "args": [] }, "UR": { "name": "copy html", "args": [] } }, "mouse_track": true, "visualized_arrow": true, "superdrag": false, "useMousewheel": true, "useTabList": false, "useSmoothScroll": false, "ScrollSpeedValue": 0.2, "useScrollAcceleration": true, "AccelerationValue": 2, "suppress_contextmenu": true, "minimumUnit": 10 } |
たまにやるけど忘れるので。スペースを含まないときは別のやり方でも開くのですが、
一般的には以下のようにします。cmdの引数にエスケープされた状態で渡すというのがキモです。
string mapの変換ルールではエスケープシーケンスが適用されることに注意します。
set office_dir {C:\Program Files\Microsoft Office} set escaped_office_dir [string map {\\ \\\\} [file nativename $office_dir]] puts [concat exec [auto_execok start] explorer $escaped_office_dir] eval exec [auto_execok start] explorer $escaped_office_dir |
– 追記
上記のスクリプトではエクスプローラで開くのが前提だったので、私のように秀丸ファイラーなどの代替ファイラーを使ってる人にとっては100%満足できるものではありませんでした。なんかこれを書いてるちょっと前にStackOverflowに同じ内容の質問が挙がってて、上記の提案をドヤ顔で投稿したところ、100%満足な回答が返ってきました。
http://bit.ly/Uu6q6N
set folderpath {C:\Program Files\Microsoft Office} exec {*}[auto_execok start] "" [file nativename $folderpath] |
いわゆる双方向連結リストというデータ構造ですが、かつてはリチャードストールマンに、Tclには構造体がないからlinked listを作れないと指摘されていました。今ではいくつもあるオブジェクト指向拡張を使い、クラスを導入すればTclでも他の言語と同じような形で実装できます。
arrayでもできますが、あまり使いやすくならないと思うので、僕はXOTclでLinkedList::ContainerとLinkedList::Elementというクラスを作っていて、これらを継承するか、mixinしたクラスは、連結リストの管理オブジェクト、リスト要素として扱えるようにしています。
通常のリストに比べると、要素が少ないうちは遅いですが、数千数万の要素数になってくるとかなり効率が違ってきます。
テストスクリプト
package require -exact linkedlist 3.0 Class ListContainer -instmixin {LinkedList::Container} Class ListElement -instmixin {LinkedList::Element} proc test_linkedlist {size} { set container [ListContainer new] for {set i 0} {$i < $size} {incr i} { $container push [ListElement new] } foreach e [$container rlist] { $container delete $e } return {} } proc test_nativelist {size} { set l {} for {set i 0} {$i < $size} {incr i} { lappend l $i } for {set i 0} {$i < $size} {incr i} { set l [lreplace $l end end] } return {} } foreach size {1000 10000 15000 20000 30000} { puts "size=$size" puts "linkedlist [time {test_linkedlist $size} 2]" puts "nativelist [time {test_nativelist $size} 2]" puts "" } |
結果
C:\Tcl\lib\linkedlist3>
tclsh test2.tcl
size=1000
linkedlist 30047.5 microseconds per iteration
nativelist 2168.5 microseconds per iteration
size=10000
linkedlist 307218.5 microseconds per iteration
nativelist 215719.0 microseconds per iteration
size=15000
linkedlist 491008.5 microseconds per iteration
nativelist 469101.5 microseconds per iteration
size=20000
linkedlist 627835.0 microseconds per iteration
nativelist 900121.5 microseconds per iteration
size=30000
linkedlist 962158.5 microseconds per iteration
nativelist 1995813.5 microseconds per iteration |
tktableなんかもarrayをデータソースにすると高速なんですが、arrayを直接操作するよりも、データの順序などを安全に扱うことができる連結リストでデータ管理するのがいいと思います。
package require XOTcl namespace import xotcl::* namespace eval LinkedList {} Class LinkedList::Container LinkedList::Container instproc init {} { my set first {} my set last {} my set size 0 next } LinkedList::Container instproc destroy {} { set es [my list] foreach e $es { my drop $e } next return $es } LinkedList::Container instproc clear {} { set es [my list] foreach e $es { $e destroy } return {} } LinkedList::Container instproc first {} { my instvar first return $first } LinkedList::Container instproc last {} { my instvar last return $last } LinkedList::Container instproc size {} { my instvar size return $size } LinkedList::Container instproc unlink {element} { my instvar size first last if {![Object isobject $element]} {return -1} if {[$element container] != [self]} {return -1} set prev [$element prev_p] set next [$element next_p] $element prev_p {} $element next_p {} $element container {} if {$prev eq {}} { set first $next } else { $prev next_p $next } if {$next eq {}} { set last $prev } else { $next prev_p $prev } incr size -1 } # private LinkedList::Container instproc add {element} { my instvar size first last if {[$element next_p] == $first} { set first $element } if {[$element prev_p] == $last} { set last $element } $element container [self] incr size return $element } LinkedList::Container instproc scan {key value} { for {set e [my first]} {$e != {}} {set e [$e next_p]} { if {[$e $key] == $value} {return $e} } } LinkedList::Container instproc at {index} { if {$index == "end"} {return [my last]} if {$index < 0 || [my size] <= $index} {return {}} set i 0 for {set e [my first]} {$e != {}} {set e [$e next_p]} { if {$i == $index} {return $e} incr i } return {}; # not found } LinkedList::Container instproc list {} { set es {} for {set e [my first]} {$e != {}} {set e [$e next_p]} { lappend es $e } return $es } LinkedList::Container instproc rlist {} { set es {} for {set e [my last]} {$e != {}} {set e [$e prev_p]} { lappend es $e } return $es } LinkedList::Container instproc index {element} { set i 0 for {set e [my first]} {$e != {}} {set e [$e next_p]} { if {$e == $element} {return $i} incr i } return -1; # not found } LinkedList::Container instproc pop {} { set last [my last] my drop $last } LinkedList::Container instproc push {element} { set last [my last] if {$last == {}} { my add $element } else { $last append $element } return $element } LinkedList::Container instproc shift {} { my drop [my first] } LinkedList::Container instproc unshift {element} { set first [my first] if {$first == {}} { my add $element } else { $first prepend $element } return $element } LinkedList::Container instproc drop {element} { if {[my unlink $element] >= 0} { return $element } } LinkedList::Container instproc delete {element} { if {![Object isobject $element]} { $element destroy } } # InstMixin this class into element class to use container Class LinkedList::Element -parameter { {prev_p {}} {next_p {}} {container {}} } LinkedList::Element instproc destroy {} { my drop next return [self] } LinkedList::Element instproc drop {} { if {[my container] != {}} { [my container] drop [self] } } LinkedList::Element instproc index {} { if {[my container] != {}} { [my container] index [self] } } LinkedList::Element instproc append {element} { if {[my container] != {}} { $element prev_p [self] $element next_p [my next_p] if {[my next_p] != {}} { [my next_p] prev_p $element } my next_p $element [my container] add $element } } LinkedList::Element instproc prepend {element} { if {[my container] != {}} { $element prev_p [my prev_p] $element next_p [self] if {[my prev_p] != {}} { [my prev_p] next_p $element } my prev_p $element [my container] add $element } } LinkedList::Element instproc status {} { append stat " container = [my container]\n" append stat " index = [my index]\n" append stat " element = [self]\n" append stat " neighbors = ([my prev_p]) => ([self]) => ([my next_p])\n" } package provide linkedlist 3.0 |
パッケージにしておきました。
linkedlist.3.0.120823
いきあたりばったりのアーキテクチャと教訓:リレーショナルデータベースの間違った使い方10項目
動的なテーブルの作成 ⇒ INSERTのトリガで月ごとのテーブル作るようにしたらINSERTが遅すぎて失敗しました。
テーブルをキャッシュとして使う ⇒ Railsではセッションキャッシュに使ってたけど、のちにcookieセッションに変わったと思う。
テーブルをキューとして使う ⇒ やりました。Dequeを使うのがいいのですが、自作のデータグリッドウィジェットと自作のTcl版ActiveRecordの依存性が高すぎて変更が大変。いまだに変えられない。
テーブルをログとして使う ⇒ 他にどうすんの?KVSってやつ?検索とか似たような機能あるの?
分散したグローバルなロック ⇒ なにそれ?
ストアドプロシージャ ⇒ 使ったことない。
使われない項目 ⇒ いくつかあるけど、そんなに多くない。検索キーにならないカラムが増えていくのを、YAML形式とかでテキストカラムに押し込めるべきか悩んでる。
ORMによって繰り返されるクエリ ⇒ よくやりました。暗黙的遅延ロード機能なんかつけるからだ。ActiveRecordなら:include=>”groups”、EFなら.Include(“groups”)を使う。
負荷のコントロール ⇒ DBじゃないけど、ウェブサーバのリバースプロキシとかはよくやりました。メモリリークだらけのRailsには必要だった。