以下のコードと同じ出力をより短いコードで得よ。(パーは 27バイト)
-2000.step(-10000,-10) do |v| puts v end
n=1990;801.times{p -n+=10}
-1 (26バイト)だからバーディーかな。アルバトロス(-3)が上限とは限らないけど。数値リテラルが冗長な気がするけど他の表現が思いつかない。文字コード(?X)を使おうと思ったけどできなかった。
irb(main):115:0> require :benchmark.to_s irb(main):119:0> Benchmark.bmbm{|j| j.report } NameError: uninitialized constant Benchmark::Job::ArgmentError from C:/Program Files (x86)/ruby/lib/ruby/1.8/benchmark.rb:333:in `report' from (irb):119 from C:/Program Files (x86)/ruby/lib/ruby/1.8/benchmark.rb:250:in `bmbm' from (irb):119 from :0 irb(main):120:0>
ArgmentError -> ArgumentError
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/44601
2.2.0に変更すると半分程度の月の日記データ(YYYYMM.td2)が消えた。残ってる月も表示されるのは一、二件程度。原因を調べると、もちろん原因は自分にあったんだけど、2.2.0の更新された tdiary/wiki_style.rbに、DIFF差分をもとに過去に自分が加えた変更をもう一度加えたときに行頭の - を一カ所取り除き忘れたのが原因だった。
if /\A(?:http|https|ftp|mailto)\z/ =~ scheme
を、
if /\A(?:http|https|ftp|mailto|javascript)\z/ =~ scheme
こう(↑)すべきところ、
- if /\A(?:http|https|ftp|mailto|javascript)\z/ =~ scheme
こう(↑)してしまったのが原因。
Rubyでは ifといえども値を返すので、Stringに単項マイナスのメソッドは存在しないというエラーになっていたんだけど、そのエラーは tdiary/defaultio.rbの restore()で rescue NameErrorされて捨てられていました。
スクリプトのエラー(原因は自分だけど)で日記データが消えるのはウレシクナイ。スクリプトの間違いは起こりやすく修正も容易だけど、消えた日記データは復活しないのだから。バックアップをとっていてさえ直前のバックアップより新しいものは元に戻しようがない。
エラーで表示できない日記データでも TDiary::WikiDiaryなどのかわりに TDiary::BadDiary などとして保持しておいてほしいな(そしてデータファイルを更新するときには正常なデータと一緒に書き込む)、と思いつきだけで書く。
(怖くなってサーバーの tDiaryがまだアップデートできてません)
セクションごとに表示されるようになったのはもちろんのこと、飛び先が同一ページ内になったことが嬉しい。プライベートな変更(→20040228p02, →20050401p01)は維持するのが面倒くさいし、アップデートの失敗例が直上にあるので。
Productize and officially support the group_concat() SQL function.
試してみる。
>sqlite3 SQLite version 3.5.4 Enter ".help" for instructions sqlite> create table t1(c1); sqlite> insert into t1 values(1); sqlite> insert into t1 values(2); sqlite> insert into t1 values(3); sqlite> select * from t1; 1 2 3 sqlite> select group_concat(c1) from t1; 1,2,3 sqlite> select group_concat(c1+1) from t1; 2,3,4 sqlite> select group_concat(c1||0) from t1; 10,20,30 sqlite> select group_concat(c1, "-") from t1; 1-2-3 sqlite> select group_concat(c1, c1) from t1; 12233
期待通り。
もう create_function()で自作して Segmentation faultに困らされたりすることもなくなるね。(sqlite3-rubyの話)
もっとも sqlite3-rubyは一年以上のブランクを経て今年の二月に新バージョンが出てるので Segmentation faultは出なくなってると思う。下の変更点が多分そう。
2007-01-13 11:42 jamis
* Fix for use of callbacks (busy_handler, set_authorize and trace) (thanks Sylvain Joyeux, closes #2955)http://rubyforge.org/frs/shownotes.php?group_id=254&release_id=9438
数日前からこちら(SmallStyle - category プラグインを利用した タグクラウド 表示プラグイン)から入手したタグクラウド表示プラグインを手直ししたものを使っている。
直した理由は、日記を書かなくても毎日キャッシュが更新されるとか(<それ日記じゃない)、すぐに組み立てられる URLをキャッシュに含めなくてもいいじゃないかとか、addとか print_htmlというメソッドにプラグインの名前空間を汚されたくないとか、プラグインファイルの地の部分で returnするとどこへ戻るんだろう無事に戻れるんだろうかとか、そういうこと。いじった結果、ファイルサイズが増加し、キャッシュサイズもたぶん増加し、計算量が増加して、機能はほとんど変わらず、なので変更点は(この人目につかない日記にも)書けない。
本題。変更の過程でフォントサイズの指定をクラスからインラインスタイルに変更し、style="font-size: xxx%" というのを HTMLタグに埋め込むことにした。そして、フォントサイズのパーセンテージの決定方法を以前自分が書いたものから流用した。(ここが問題)。
以前書いたものはタグの出現数の分布を、最小フォントサイズ(100%)から最大フォントサイズ(200%)の間にそのままマップするものだった。これだと一つだけ突出したタグがあると他がみんなどんぐりの背比べになってしまう。では出現数の二乗根を使うとどうなるか、実験してみた。
[1, 2, 3, 10, 20, 50] # タグの出現数のリスト => [100, 102, 104, 118, 138, 200] # 出現数をそのまま使って font-size(100%-200%)を求めた => [100, 106, 112, 135, 157, 200] # √出現数 => [100, 117, 128, 158, 176, 200] # log(e)(出現数)
ここの日記のように一部のタグだけが突出していて、その他のほとんどのタグの出現数が 10以下のような場合は、出現数の自然対数を使うと出現数のわずかな増加にフォントサイズが敏感に反応する。というわけで、Rubyでは sqrtと logの時間コストがほとんど同じであることだし、タイトルを無視して logを使ってフォントサイズを決めることにした。
単純に出現数を使った場合、上で書いたように一つを除いて豆粒サイズになる問題があったが、logを使った場合は一部を除いほとんどが最大に近いサイズになってしまう問題が発覚した。あいだをとってルート。
http://www.machu.jp/diary/20070719.html#p02
はてブ指数というものに使われているという。定義は「N以上の数がN個以上含まれる場合の最大のN」
これなら一部のカテゴリがどれだけ突出していていようとも、「N以上である」としか評価されないわけだ。たとえば求めた H指数が 100だったとき、値が100の要素も10000の要素も「100以上である」とだけ評価されているわけで、重みは等しい。なるほど。でも H指数をフォントサイズの決定にどのように使おう。
アップデートして、カスタマイズしたファイルが上書きされたり、設定が消えたり、新たな不具合を拾ったりしたらたまらないのでインストールはしない。4.00に不満もないしね > 11月2日を参照
それはそれとして、Logicoolはソフトウェアの更新履歴とか既知の不具合とか明らかにしたらどう。キャンセルボタンを押したらキー割り当ての設定が消えるなんて問題を直しもせず周知もせずほっとくなんて許せん。
Brief summary:
- Firmware update (92) for Logitech Bluetooth 2.0 receivers
- C++ redistributable package update
- Logitech Updater with new UI
Ligitech(英語)のサイトでは一応情報が出てた。Logicool、使えない。
http://logitech-en-amr.custhelp.com/cgi-bin/logitech_en_amr.cfg/php/enduser/std_adp.php?p_faqid=7776
10月22日に書いたように「カテゴリ」表示モードは「最新」「月」表示と見た目が違って違和感があるので、カテゴリ表示を最新表示と月表示に近づけてみた。(この日記で実働中)。
新しく表示モード(TDiaryViewを継承したクラス)を作るのは手間だし、TDiaryLatestや TDiaryMonthからのコピペばっかりになることが想像できるので IOのラッパを作って TDiaryLatestや TDiaryMonthを騙すことに。
transactionメソッドを引っかけて元々の IO(DefaultIOか PStoreIO)が渡してきた diariesから特定のカテゴリを持たないセクションを取り除いて呼び出し元に渡す。
transactionの呼び出し元に不完全な日記データが渡る関係上、日記の変更は捨てる。(読み出し専用)
個々の日記のURLを ?date=yyyymmdd から yyyymmdd.html に、mod_rewriteを使って書き換えてる場合、RewriteRuleの最後に [QSA] (query string append)フラグを付けて書き換えた URLにクエリストリングをくっつけてもらう必要がある。クエリストリングはカテゴリを指定するのに使う。mod_rewriteを使っていない場合は .htaccessの変更は必要ない。
RewriteEngine on RewriteBase /ds14050/diary RewriteRule ^([0-9]+)(-[0-9]+)?\.html$ index.rb?date=$1$2 [QSA]
カテゴリの指定に categoryという CGIパラメータを使うので、最新表示にカテゴリフィルタをかけたときの URLが index.rb?category=カテゴリ になり、最後の else まで落ちて最新表示が選択される前に、従来のカテゴリ表示が選択されてしまう。これまでのカテゴリ表示は使わないので該当する二行をコメントアウトする。
if @cgi.valid?( 'comment' ) then …… elsif @cgi.valid?( 'date' ) …… # elsif @cgi.valid?( 'category' ) # tdiary = TDiary::TDiaryCategoryView::new( @cgi, "category.rhtml", conf ) elsif @cgi.valid?( 'search' ) …… else …… end
騙すのは TDiaryLatestと TDiaryMonth。それぞれの initialize()で日記データを読み出す前に、@ioを置き換えるコードを追加する。CategorizedIOは読み出し専用なのでこれ以後 日記の変更はできなくなるが、どちらも日記の変更はしていない(と思う)ので影響はない。
また categoryパラメータが与えられたときにキャッシュを無効にするために cache_file() も変更している。
class TDiaryView < TDiaryBase
(skip)
def load_categorizedio( baseio ) # CategorizedIO is an IO wrapper and is readonly. return baseio if not @conf or not @cgi require 'tdiary/categorizedio' category_dir = File.join(@conf.data_path, 'category') categories = ( @cgi.params['category'] || [] ) return CategorizedIO.new( baseio, category_dir, categories ) end end # # class TDiaryDay # show day mode view # class TDiaryDay < TDiaryView
(skip)
class TDiaryMonth < TDiaryView def initialize( cgi, rhtml, conf ) super @io = load_categorizedio( @io ) begin
(skip)
protected def cache_file( prefix ) @cgi.valid?( 'category' ) ? nil : "#{prefix}#{@rhtml.sub( /month/, @date.strftime( '%Y%m' ) ).sub( /\.rhtml$/, '.rb' )}" end end # class TDiaryMonth
(skip)
class TDiaryLatest < TDiaryView def initialize( cgi, rhtml, conf ) super @io = load_categorizedio( @io )
(snip)
def cache_file( prefix ) if @cgi.params['date'][0] or @cgi.valid?( 'category' ) then nil else "#{prefix}#{@rhtml.sub( /\.rhtml$/, '.rb' )}" end end
(skip)
end # class TDiaryLatest
新規追加ファイル。貼り付けるには厳しい量だな。貼るけど。
既存の IOのメソッドを置き換えるのは transaction() と calendar() の二つ。
transaction() は該当するカテゴリを持たないセクションをはじく機能を持つ。
calendar() は該当するカテゴリを持つセクション の存在する年月のみを返す。calendarを作成するために category.rbプラグインが作成するキャッシュを利用するのでキャッシュが壊れていたり不完全だったりすると影響を受ける。
HOWTO-make-plugin.html には TDiary::Plugin@yearsには全日記の年月データが含まれていると明記されているので、@yearsの元になる calendarを上書きすると category.rbや squeeze.rbなど独自に日記を読み込むプラグインが期待通り動かない可能性がある。
@io.transactionで TDiary::TDiaryBase::DIRTY_NONEを返しても DefaultIOがデータを更新することがある。キャッシュが存在しない場合がそう。yieldを呼び出した後で、CategorizedIOがセクションを削除したりした diariesを元にキャッシュを作成してしまう。今は tdiary/defaultio.rbを書き換えて yieldを呼び出す前に必要ならキャッシュを作成してしまって、yieldの戻り値が DIRTY_NONE以外だった場合は、もう一度キャッシュを作成しなおすようにしているが、単純に tdiary/caretorizedio.rbで DefaultIO#transactionを breakで抜けてもいい。 DefaultIO#transactionを抜けてから diariesをいじるようにして解決済み。
表示しないセクションを削除してしまうとセクションナンバーが変わってしまい、それに伴って URLも変わってしまうので混乱を招くもとになっていた。 12月28日に tdiary/categorizedio.rbを修正して解決済み。
require 'delegate' require 'pstore' module TDiary class CategorizedIO < SimpleDelegator def initialize(baseio, category_dir, categories=nil) super(baseio); @dir = category_dir; set_categories(categories); end def set_categories(categories) @categories = (categories || []); @calendar = nil; # update calendar end def categorized? return(@categories and !@categories.empty?); end def calendar return __getobj__.calendar unless categorized?; @calendar = category_calendar unless @calendar; return @calendar; end # 読み出し専用。ブロック引数を変更しても元々の IO(DefaultIO or PStoreIO)には届きません。 def transaction(date, &block) if(not categorized?) return __getobj__.transaction(date, &block); elsif(! block) # nothing to do. elsif(in_calendar?(date)) diaries = nil; __getobj__.transaction(date){|diar_es| diaries = diar_es; TDiaryBase::DIRTY_NONE; } if(diaries) filtered_diaries = category_filter(diaries); dirty = yield(filtered_diaries); end else yield({}); end end private def category_filter(diaries) filtered = {}; diaries.each{|ymd, diary| next unless diary.categorizable?; diary_is_empty = true; diary.each_section{|section| if((@categories - section.categories).empty?) diary_is_empty = false; else hide_section(section); end } filtered[ymd] = diary unless diary_is_empty; } return filtered; end def hide_section(section) section.extend(HiddenSection); end def in_calendar?(date) y, m = "000#{date.year}"[-4,4], "0#{date.month}"[-2,2]; cal = self.calendar; return(cal.has_key?(y) && cal[y].include?(m)); end # returns intersection of all @categories' calendar. def category_calendar years = __getobj__.calendar; categories = (@categories || []); ymdp_array = nil; categorize(categories, years).each{|ctgr, ctgr_cache| a = []; ctgr_cache.each{|ymd, day_cache| day_cache.each{|cache| section_index, = *cache; a.push(ymd+'p'+section_index.to_s); } }; ymdp_array = ymdp_array.nil? ? a : (ymdp_array & a); break if ymdp_array.empty?; }; category_calendar = {}; ymdp_array.each{|ymdp| y, m = ymdp[0,4], ymdp[4,2]; months = (category_calendar[y] ||= []); months.push(m) unless months.member?(m); } return category_calendar; end # following code is from plugin/category.rb (--;) !DRY # # categorize sections of category of years # # {"category" => {"yyyymmdd" => [[idx, title, excerpt], ...], ...}, ...} # def categorize(category, years) categories = category - ['ALL'] if categories.empty? categories = restore_categories else categories &= restore_categories end categorized = {} categories.each do |c| PStore.new(cache_file(c)).transaction do |db| categorized[c] = db['category'] db.abort end categorized[c].keys.each do |ymd| y, m = ymd[0,4], ymd[4,2] if years[y].nil? or !years[y].include?(m) categorized[c].delete(ymd) end end categorized.delete(c) if categorized[c].empty? end categorized end # # restore category names # ["category1", "category2", ...] # def restore_categories list = nil PStore.new(cache_file).transaction do |db| list = db['category'] if db.root?('category') db.abort end list || [] end def cache_file(category = nil) if category "#{@dir}/#{ERB::Util.u( category ).gsub(/%20/,'+')}".untaint else "#{@dir}/category_list" end end end module HiddenSection def html4(date, idx, opt) return <<-"HTML"; <% section_enter_proc( Time::at( #{date.to_i} ) )%> <% section_leave_proc( Time::at( #{date.to_i} ) )%> HTML end def chtml(date, idx, opt) return html4(date, idx, opt); end def subtitle_to_html return ''; end def body_to_html return ''; end def stripped_subtitle_to_html return ''; end end end
ナビリンクとカレンダーを categoryパラメータ対応に。c_anchor() がカテゴリに対応した anchor()で、この後で category.rbに追加する。
def navi_user_latest anchor = method(respond_to?(:c_anchor) ? :c_anchor : :anchor) result = '' result << navi_item( "#{@index}#{anchor.call( @conf['ndays.next'] + '-' + @conf.latest_limit.to_s )}", navi_next_ndays ) if @conf['ndays.next'] and not bot? result << navi_item( @index, navi_latest ) if @cgi.params['date'][0] result << navi_item( "#{@index}#{anchor.call( @conf['ndays.prev'] + '-' + @conf.latest_limit.to_s )}", navi_prev_ndays ) if @conf['ndays.prev'] and not bot? result end
def navi_user_month …… anchor = method(respond_to?(:c_anchor) ? :c_anchor : :anchor) result = '' result << navi_item( "#{@index}#{anchor.call( prev_month )}", navi_prev_month ) if prev_month and not bot? result << navi_item( @index, navi_latest ) result << navi_item( "#{@index}#{anchor.call( next_month )}", navi_next_month ) if next_month and not bot? result end
def calendar result = %Q[<div class="calendar">\n] @years.keys.sort.each do |year| result << %Q[<div class="year">#{year}|] @years[year.to_s].sort.each do |month| m = "#{year}#{month}" if(respond_to? :c_anchor) result << %Q[<a href="#{@index}#{c_anchor m}">#{month}</a>|] else result << %Q[<a href="#{@index}#{anchor m}">#{month}</a>|] end end result << "</div>\n" end result << "</div>" end
c_anchor プラグインメソッドを追加。カテゴリパラメータに対応した anchorメソッド。
def c_anchor(s) a = anchor(s) return a unless @category_info a << (a.index('?') ? ';' : '?') a << @category_info.query_string a.chomp!(';'); a.chomp!('?') return a end # # misc #
既存の make_anchor()メソッドの前半からクエリストリング作成部分を query_string()メソッドとして切り出し。上の c_anchor()で利用するために。
def make_anchor(label = nil) if label case mode when :year label = label.gsub(/\$1/, @year) when :month, :quarter, :half label = label.gsub(/\$2/, @month) label = label.gsub(/\$1/, @year || '*') end else label = @category.map {|c| CGI.escapeHTML(c)}.join(':') end %Q|<a href="#{@conf.index}?#{query_string}">#{label}</a>| end def query_string qs = @category.map {|c| "category=#{CGI.escape(c)}"}.join(';') qs << ";year=#{@year}" if @year qs << ";month=#{@month}" if @month qs end
Category::Infoを毎回作るのが面倒なのでインスタンス変数として保持。
@categories = @category_cache.restore_categories @category_info = Category::Info.new(@cgi, @years, @conf) if @mode == 'categoryview' @categorized = @category_cache.categorize(@category_info.category, @category_info.years) end
検索結果の表示も同じ方法でできる。スコア順に表示したりはできないけど、特定の語を含む日記を時系列順に閲覧することはできる。ワードフィルタ? IOの三段重ねでワードフィルタとカテゴリフィルタを両方適用することもできるね。
やってみた@2007-12-18。→http://vvvvvv.sakura.ne.jp/ds14050/diary/?word=windows
単語のハイライトとかナビゲーションリンクの対応とかカレンダーをどうするかとかは一切放置。本当にやってみただけ。word=WORD1というパラメータを付ければ「月別」「最新」「カテゴリ」表示のどれでもフィルタリングできるはず。
2008年の 1月頃から約 1年間、上記のリンク先が Internal Server Errorになっていたもよう。なんたる無様。それに気付くきっかけが連日のコメントスパムというのがなんともはや。
数字を列挙したファイルがあるので、この数字を加工せずにそのまま放り込んだら X軸と Y軸の上限と原点を適当に決めて、見られるグラフになったりすると便利だな、と思って。(はてなグラフは知ってるけど id持ってないので)
viewBox属性を使うと空間の 原点と大きさを自由に定義できるので、与えられた数字の最小値と最大値とその差を使って viewBoxを定めると、入力された数字を加工せずとも点が端から端までをフルに使って配置されて具合がよい。
で、viewBoxという仮想平面を表示するときには表示サイズまで拡大縮小をする必要があって、このときに線の太さが一緒に拡大縮小されて( ゜Д゜)マズー というのがいま。
Inkscapeというベクタ画像ソフトは、[File]->[Inkscape Preference]->[Transforms]タブ->[Scale stroke width] のチェックを外す、という手順でこれを回避できるらしいのだけど、SVGにはそのものズバリの属性はないのかね。
http://www.nabble.com/Stroke-width-bug--t4712455.html
Q「単位をつけてるのに拡大されたり縮小されたりするのっておかしくね? A「全部相対的なもんだ Q「仕様にそういうふうに書いてあるとは思わない A「CSSの ptとか pcとか cmとか mmっていう単位は全部 pxの何倍かっていうのを示してるだけなんだよ Q「わかった。でオフトピだけどこの問題を解決する方法はあるの? A「javascriptを使って逆の拡大縮小をかけるしかない。SVG1.2になればなんとかなってるかもしれない B「Mozillaの SVGを最初に実装した alex fritzeは正に今のようなことを考えて実装をしたと思う(I believe)。それが the mozila codebaseに投稿されて受理されたかは知らないけど
こんな雰囲気だろうか
その図形に対して javascriptで逆の拡大縮小をかけろっていってるけど、座標をスケールさせたままで線の太さだけを元に戻せるのだろうか。
squeeze.rbによる HTMLファイルが既にあるし、ってことでただの grepの出力を HTMLに整形するだけのもの。タイトルとかサブタイトルを参照してもうちょっと見やすく整えたり、AND検索のときの出力に最後の検索語しか現れないのをなんとかしたりとか、そんなことの前に検索対象を間違えてることにいま気付いた。
td2 | html | |
---|---|---|
2006 | 127KB@12files | 981KB@130files |
2007 | 164KB@11files | 1.03MB@97files |
td2を読まないと……(__;) Namazuのインデックスのサイズだって元のデータが小さいからたかがしれてるぞ。
etDiary用のスプリッタ( 'etdiary' => /^<<(?!<)/ )を加えたのと、Wiki用のスプリッタを /^!/ から /^!(?!!)/ に変更したのと、本文のない日があるとその次の日を加えた二日分をまとめて読んで一日としてしまうことがあったので read_diaries(path) をごにょごにょと泥臭く修正した。
最終更新: 2010-01-12T06:09+0900
Vistaに対応した最初の SetPoint version 4.00がリリースされてから一度もアップデートがないのだけど。
MX610に同梱されてた SetPointから続く、Firefoxに Ctrl+Wを投げてウィンドウを閉じると時々 Ctrlキーが押し下げ状態のままになってしまって、Ctrlキーを一度押し直して解除してやる必要に迫られる問題は残されたまま。
Ctrlの状態が見えないものだから、スクロールしようとホイールを回して文字サイズが大きくなってはじめて気付くことになる。それにびくついてしまって Ctrl+Wを割り当てた中ボタンを使わずに右上の×印までポインタを持って行って閉じてみたり、中ボタンで閉じてから心配になって Ctrlキーをたたいてみたりして、いまいち手間を省けてなかった。
気づいたんだけどウィンドウを閉じてしまうようなキーストロークって使ってるのは Ctrl+Wだけで、その Ctrl+Wを送ってるのもエクスプローラと Firefoxと「その他すべてのプログラム」の 3つだけだった。
SendInputっていう APIを試してみたけど Ctrlが残るようなことは起こらなかった。で、ひとつの解決法。
#include <windows.h> #define numof(array) (sizeof(array)/sizeof(array[0])) int main() { INPUT inputs[] = { {INPUT_KEYBOARD}, {INPUT_KEYBOARD}, {INPUT_KEYBOARD}, {INPUT_KEYBOARD} }; inputs[0].ki.wVk = VK_CONTROL; inputs[0].ki.wScan = 0; inputs[0].ki.dwFlags = 0; inputs[0].ki.time = 0; inputs[0].ki.dwExtraInfo = NULL; inputs[1].ki.wVk = 'W'; inputs[1].ki.wScan = 0; inputs[1].ki.dwFlags = 0; inputs[1].ki.time = 0; inputs[1].ki.dwExtraInfo = NULL; inputs[2].ki.wVk = 'W'; inputs[2].ki.wScan = 0; inputs[2].ki.dwFlags = KEYEVENTF_KEYUP; inputs[2].ki.time = 0; inputs[2].ki.dwExtraInfo = NULL; inputs[3].ki.wVk = VK_CONTROL; inputs[3].ki.wScan = 0; inputs[3].ki.dwFlags = KEYEVENTF_KEYUP; inputs[3].ki.time = 0; inputs[3].ki.dwExtraInfo = NULL; SendInput(numof(inputs), inputs, sizeof INPUT); return 0; }
>cmd /V:ON >"C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\SetEnv.Cmd" /Vista /Release >cl "^W.cpp" /link /SUBSYSTEM:WINDOWS /nodefaultlib /entry:main user32.lib
うへっ、しょーもねー。(でも必要十分にして手放せない)
エクスプローラや Firefoxや SakuraEditorなどは OKなんだけど、気付いたところでは Hamanaだけが Ctrl+Wではなく Wというキーストロークが送られたとしか受け取ってくれない。ゲームとかハードウェアに近いレイヤーで入力を受け取ってそうなものが結構ダメかもしれない。わからんけど。そうだとしたら SetPointとしては無視できないよね。ゲームにキーストロークが送れないとか。(自分にとってはそのせいで抱え込む誤動作の方が無視できないわけだけど)
WSHで WScript.Shell.SendKeysを使えば、メモ帳だけで解決できる。たぶん起動時間は気にならない程度になっているだろう。
これだけ。
new ActiveXObject("WScript.Shell").SendKeys("^w");
これを ^W.jsとでも保存して SetPointでボタンに割り当てるだけ。拡張子が exeでないファイルはデフォルトでは表示されないが問題なく割り当てられるし実行もできる(少なくとも Vistaでは確認した)。これだけ簡単だと "^w" の部分をハードコードせずに、引数として任意のキーストロークを表す文字列を受け取りたくなるが、SetPointが引数付きでプログラムを起動してくれないのでできなかった。(ちなみに Alt+F4なら "%{F4}" になる)
気になる起動時間は、exeと遜色ないくらい一瞬だった。ちなみにマシンスペックは
Windows エクスペリエンス インデックス サブスコア | ||
プロセッサ | Athlon64 X2 3800+ | 4.8 |
メモリ(RAM) | DDR 2GiB | 5.5 |
1、2年前に既にこなれた値段で売られていたようなもの。
* JScript@WSHと C#@.NET1.0の起動に 20-30秒くらいかかっていた、メモリ 64MBのあの頃
XPのときと違って AMDから Cool'n'Quiet用のドライバが提供されなくて、Vistaではマイクロソフト任せなんだけど Vistaにしてから効いてなかった。
もっと早くに更新しとけば良かった。自分に関係のある変更がなかったので放置してたよ。
ソフトは HD Tuneと CrystalDiskMarkの二種類。
測定対象となる HDDは三つ。
HDS728080PLA380 | HDT725050VLA | HPT DISK 0_0 | |
Transfer Rate Minimum | 9.6 MB/sec | 38.0 MB/sec | 23.6 MB/sec |
Transfer Rate Maximum | 57.7 MB/sec | 74.4 MB/sec | 103.8 MB/sec |
Transfer Rate Average | 43.4 MB/sec | 62.1 MB/sec | 81.7 MB/sec |
Access Time | 13.8 ms | 13.6 ms | 13.7 ms |
Burst Rate | 94.1 MB/sec | 142.9 MB/sec | 90.1 MB/sec |
CPU Usage | 14.4% | 14.4% | 20.7% |
HDS728080PLA380 | HDT725050VLA | HPT DISK 0_0 | |
Sequential Read | 42.529 MB/s | 67.832 MB/s | 79.365 MB/s |
Sequential Write | 29.240 MB/s | 53.996 MB/s | 71.782 MB/s |
Random Read 512KB | 23.221 MB/s | 41.875 MB/s | 45.955 MB/s |
Random Write 512KB | 1.300 MB/s | 1.626 MB/s | 24.938 MB/s |
Random Read 4KB | 0.782 MB/s | 1.848 MB/s | 6.413 MB/s |
Random Write 4KB | 1.504 MB/s | 1.903 MB/s | 1.059 MB/s |
HDS728080PLA380 | HDT725050VLA | HPT DISK 0_0 | |
Sequential Read | 46.69 MB/s | 44.68 MB/s | 68.16 MB/s |
Sequential Write | 32.75 MB/s | 39.79 MB/s | 61.32 MB/s |
Random Read 512KB | 23.57 MB/s | 28.41 MB/s | 32.78 MB/s |
Random Write 512KB | 16.30 MB/s | 31.06 MB/s | 21.86 MB/s |
Random Read 4KB | 0.38 MB/s | 0.407 MB/s | 0.697 MB/s |
Random Write 4KB | 1.04 MB/s | 1.162 MB/s | 0.429 MB/s |
ケータイ用のメインメニューだが Flashなのでパソコンでも見られるし操作もできる。
頑張れリスモは時間帯によって変化するリスモを愛でるのが第一目的のメニューだが、このバージョンはメニューの操作方法が他とちょっと違ってて使いやすそうだった。*
メニュー項目はよくある 4×3配置。下は模式図。menu22にフォーカスがある。
menu11 menu12 menu13 menu21 << menu22 >> menu23 menu31 menu32 menu33 menu41 menu42 menu43
パソコンでも操作できると書いたが使えるキーは↑か↓しかない。←と→は使えない。フォーカスは上下には移動するが左右には移動しないということ。これの意味するところを想像するに、←と→はフォーカスの移動ではなくメニューアイテムの起動を行っているのだろう。PCで見ているから起動を確認することができないが。一列目と三列目が、予めフォーカスを持っている二列目と同じ操作数で起動できるのだ。
ショートカットキー(アイコンの位置に応じて数字キー一発でアイテムを起動すること)が使えないうえ、アイコンにフォーカスを合わせてから決定ボタンで起動するよくある 4×3メニューより優れてるのはもちろん、ソニーエリクソンのプリセットメニューの一つの縦に 12の項目が並んだメニューよりも使いやすい。いくらジョグが縦移動に優れてるとはいえ最長で 6項目移動してから決定ボタンを押すよりも、最長で 2項目移動+ボタン一つ(←or決定or→)のほうが操作数が少なく感じるというもの。
(アイコンを並べてみただけの)4×3メニューやリストメニューや XMB形式⁑のメニューしか知らなくて、目から鱗の第四のメニュー形式でした。
CD-Rに mp3を焼いて CDプレイヤー(CMT-SE3)で再生しても曲単位のシャッフル再生しかできなくてがっかりしたわけだけど、iPod touchでも。
そもそも 3G iPodがアルバム単位のシャッフルという概念を俺にもたらしたんだってのに。がっかりがっかり。シャッフルモードを再生中に切り換えられるのは便利だけど、選びたいモードがなければ意味なし。
タッチボタンの iPodとして期待してたが容量も少ないし期待には応えてくれない。
この1年で大きく進歩した「Windows Vista x64」 (ITPro) iPod classicは使えるけど iPod touchは 64-bit Vistaでは使えない。
HP ProLiant ML115 が安すぎる。
Athlon64 3500+ (2.2GHz, 512KB L2) PC2-5300 DDR2 アンバッファ ECC SDRAM 512MB×1 (空きスロット3) SATA 80GB HDD 48倍速 IDE CD-ROMドライブ 1年間保証(1年パーツ保証、1年翌日オンサイト保守) オンボード 4ポート SATAコントローラ(RAID 0,1,5対応) オンボード NC320i PCI-Express Gigabitサーバ アダプタ キーボード/マウス (1×PCIe x16, 1×PCIe x8, 2×32ビット/33MHz PCI)
これで送料込み特価 18900円。(特価でない時は 40000円ほど)
玄蔵が HDD4台分のケースと電源と eSATA(PM)<->5ポートSATA変換機能だけで 20000円前後なのと比べてどう? あれこれおまけが付いてなお安い。懸念材料は普通の PC並みであろう消費電力のみ。
玄蔵。ケースは金属でしっかりしている。前面はちゃちいプラスチック。W53Sの液晶側と似た感じ(´・ω・`)
LEDは誰かが書いていた通りアクセスのない時に点灯し、アクセスがあると点滅するように見える。PCの電源を落とすと LEDは消灯していた。(電源を入れたのに LEDが消えたまま⇒HDD死亡 という判断ができる)
ファンの青色LEDはいらない。
ケースを触ると相当振動してる。今は大丈夫だけどうなりがうるさかったりした。
RAIDの初期化で二時間以上、全HDDにアクセスしている状態だが S.M.A.R.T.によると各HDDの温度は
わかりやすく、下に設置した HDDほど温度が高い。冷却ファンが背面上部にあることと HDDの底に電源があることが原因。センチュリーのドライブドア SATAボックスレイド(EX35PM4B-PE)のようにファンと HDDの間を基盤がさえぎることはないのでまだマシな方だと思う。ケースの電源部分にスリットでもあればなお良かったかもしれない。
恐ろしいのは SN25Pの中の HDDの方がよっぽど熱くなってるだろうということ。あのケースは CPUを冷やすことしか考えていない。グラフィックカードも HDDも冷えない。PCI-Express x1に差したカードもすぐ後ろのグラフィックカードからの排熱で破壊されそう。それなのに SpeedFanでコントロールしてやらないと HDDファンは 15%より回転が上昇することがない*。SN25Pが静かなのは冷却能力が十分なんじゃなくて温度上昇に無頓着なだけ。
* BIOSでファンの設定を「Smart Fan」や 「Noise Control - Mid」にしたとき。
最近マウス(Logicool MX610)の左チルト(ホイールを左に傾ける)が全く効かなくなっている。タブの切り換えに使っているので使用頻度が高くて困る。最近はおさまってるが左ボタンや右ボタンでドラッグ中のアイコンを落っことすのも再発は時間の問題でしかない。
スイッチをまち針で分解して接点にこいつをぬりぬりしたところ左チルトは完全復活。どれぐらいもつかな。SetPointには不満もあるけど MX610のボタンの多さは他のマウスでは換えられない。まだ使う。
本当は接点の汚れを落とすもの(アルコールでも代用できるとか)が欲しかった。でもアマゾンにないし、これが一番近くて、適量で、道具もセットになっていたので。
♭ ds14050http://www.mstarmetro.net/users/rlowens/?n=SetPoint.StuckM..