Warning: preg_grep() [function.preg-grep]: Compilation failed: nothing to repeat at offset 1 in /home/users/0/main.jp-yusuke-blog/web/wp-content/plugins/xlanguage/xlanguage.php on line 634

Warning: array_shift() expects parameter 1 to be array, boolean given in /home/users/0/main.jp-yusuke-blog/web/wp-content/plugins/xlanguage/xlanguage.php on line 637
I like Tcl/Tk.

I like Tcl/Tk.

クリーンルームに持ち込めるキャリーバッグ

エレファインで入手可 台湾製 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

2013/04/08 at 11:17 Comments (0)

UI Automation Clients

UI Automationについて参考になりそうなページを50個ほどブックマークしたものの、多すぎるので入口として役立ちそうなページを抜粋しておく。
本来はUIテストやアクセシビリティを目的としているようだが、今回は他人が作ったソフトを自動制御するために使う。
プロバイダとクライアントの説明があるが、今回はクライアントのことが分かればよいはず。
Windows Forms、WPF、サードパーティのUIコンポーネントでもたいていはオートメーションプロバイダとして扱えるようだ。
確証はないがUISpy.exeを使ってAutomationIdなどが確認できれば対応していると思っていいのではないかと思っている。

UI Automation のススメ

UI Automation Fundamentals

UI Automation Client Programmer’s Guide (Windows)

Use the AutomationID Property

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があるのに何でラッパーを作る必要があるのかは気になるが、まだ調べてない。


2013/01/24 at 15:32 Comments (0)

Tclでベクトル計算するサンプル

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とかも使ってない。
ロボットの研究室にいたのに行列計算が苦手というのは勉強してなかった証拠ですね。

,
2013/01/10 at 11:55 Comments (0)

Tcl SQLite build configuration

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.

Ref. 暗号化APIを有効にしたSQLite3のTclバインディングをコンパイルする

,
2013/01/09 at 19:53 Comments (2)

ネットワークアドレス変換関連の用語

NAT (Network Address Translation)

グローバルIPとローカルIPを1:1対応させる。

NAPT (Network Address Port Translation)

グローバルIPアドレスとポート番号のペアをローカルIPとポート番号のペアに1:1対応させる。

NAPTには多数の同義語が存在する

  • IPマスカレードはNAPTのLinuxにおける実装。
  • NATP(NAT+)、PAT(Port Address Translation)
  • ポートマッピング、ポートフォワーディング
  • 仮想サーバー、バーチャルサーバー、ローカルサーバー
  • NATオーバーロード、オーバーロード変換

静的NAT、静的NAPTは外部から内部のネットワークへのアクセスに使う。一般的なブロードバンドルータの設定に存在するのはこれらの設定。

動的NAT、動的NAPTは内部から外部への通信に対する応答が、送信元に返るようにするための機能であり、通常ユーザーが意識することはない。

と思う。

参考

IPマスカレード(NAPT,PAT,NAT+)を設定する

NAT と IPマスカレード(ポートフォワーディング) について

4.インターネットへの接続形態

2013/01/07 at 11:04 Comments (0)

Excelオートシェイプでフリーフォームの頂点を直角にする

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
, ,
2012/10/16 at 20:17 Comments (0)

かざぐるマウスからGestures for Chrome (ChromeGesture)に乗り換え。

林檎の木で紹介されてた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
}
, , ,
2012/10/05 at 10:32 Comments (0)

Tcl/Tkで任意のフォルダをエクスプローラデフォルトファイラーで開く

たまにやるけど忘れるので。スペースを含まないときは別のやり方でも開くのですが、
一般的には以下のようにします。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]

2012/09/06 at 14:40 Comments (0)

LinkedList in XOTcl

いわゆる双方向連結リストというデータ構造ですが、かつてはリチャードストールマンに、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

,
2012/08/23 at 21:46 Comments (0)

過去にやった「リレーショナルデータベースの間違った使い方」

いきあたりばったりのアーキテクチャと教訓:リレーショナルデータベースの間違った使い方10項目

動的なテーブルの作成 ⇒ INSERTのトリガで月ごとのテーブル作るようにしたらINSERTが遅すぎて失敗しました。
テーブルをキャッシュとして使う ⇒ Railsではセッションキャッシュに使ってたけど、のちにcookieセッションに変わったと思う。
テーブルをキューとして使う ⇒ やりました。Dequeを使うのがいいのですが、自作のデータグリッドウィジェットと自作のTcl版ActiveRecordの依存性が高すぎて変更が大変。いまだに変えられない。
テーブルをログとして使う ⇒ 他にどうすんの?KVSってやつ?検索とか似たような機能あるの?
分散したグローバルなロック ⇒ なにそれ?
ストアドプロシージャ ⇒ 使ったことない。
使われない項目 ⇒ いくつかあるけど、そんなに多くない。検索キーにならないカラムが増えていくのを、YAML形式とかでテキストカラムに押し込めるべきか悩んでる。
ORMによって繰り返されるクエリ ⇒ よくやりました。暗黙的遅延ロード機能なんかつけるからだ。ActiveRecordなら:include=>”groups”、EFなら.Include(“groups”)を使う。
負荷のコントロール ⇒ DBじゃないけど、ウェブサーバのリバースプロキシとかはよくやりました。メモリリークだらけのRailsには必要だった。

, ,
2012/08/02 at 23:26 Comments (0)

« Older Posts