メイン

ProgramMemo アーカイブ

2006年11月10日

TrueDBGridヤバイ

ヤバイ。TrueDBGridヤバイ。まじでヤバイよ、マジヤバイ。
TrueDBGridヤバイ。
まずバグい。もうバグいなんてもんじゃない。超バグい。
バグいとかっても
「偶にNullRefecence出る位?」
とか、もう、そういうレベルじゃない。
何しろ消える。スゲェ!なんかデザイナから消えるの。デザインしても勝手に消える。デザイナが生成したソースも丸ごと消える。
しかも突然消えるみたい。ヤバイよ、突然消えるんだよ。
だって普通はTextBoxとか消えないじゃん。
だって丹精込めてレイアウトしたラベルとかボタンとかが急に消えたら困るじゃん。納品したら検索ボタンが無かったとか超困るっしょ。
単体テストも結合テストも済んで、クライアントに見てもらったら入力グリッドが無かったら泣くっしょ。
だから普通のコントロールは消えない。話のわかるヤツだ。
けどTrueDBGridはヤバイ。そんなの気にしない。消えまくり。
何時消えたのかも判らず、実行してみてTrueDBGridの参照がnullになってるのでやっと判る。ヤバすぎ。
突然っていたけど、なにかしらトリガーがあるのかもしんない。でも消える原因が有るって事にすると
「じゃあ、その原因ってってナニよ?」
って事になるし、それは誰もわからない。ヤバイ。誰にも分からないなんて凄すぎる。
あと超高い。約82,000円。ベネズエラで言うと1,496,000ボリバル。ヤバイ。高すぎ。コレ採用してダメだったらマジ殺される。怖い。
それに超使いにくい。プロパティは意味不明だし。再描画も動作しないタイミング多いし。ヘルプも直訳が平気で出てくる。直訳って。韓国MMOでも言わない、最近。
なんつってもヘルプに書かれていることがその通り動かない。
うちらなんてなるべく判りやすくしようと思って一つの機能は一つの設定で動作するように設計するのに。
TrueDBGridは全然平気。幾つかのプロパティやイベント設定の複合効果でやっと編集時のフォーマットと表示時のフォーマットを変えられる。凄い。ヤバイ。
とにかく貴様ら、TrueDBGridのヤバさをもっと知るべきだと思います。
そんなヤバイTrueDBGrid使ってるオレ超偉い。もっとがんばれ。超がんばれ。

------------------------------------------------------
今開発してるアプリの殆どの時間がTrueDBGridと格闘してます。
作っては消え、作っては消え・・・・・マジで進みません。泣きそうです。

2006年08月28日

Oracleで階層問い合わせ

ツリー構成みたいなデータって良くありますけど、これをクエリする場合に便利なテクニックです。

次の様なテーブル構成、データを例にします。
[テーブル]
 ID   家族ID 
 PARENTID   親ID 
 NAME   名称 
 SEX   性別 

[データ]
上記のテーブルで次の家族を表すとします。
与作
 ├忠志
 │ └秀樹
 └慶子
   ├翔
   └萌美

 ID   PARENTID   NAME   SEX 
 1   0   与作   0 
 2   1   忠志   0 
 3   1   慶子   1 
 4   2   秀樹   0 
 5   3   翔   0 
 6   3   萌美   1 

以上のような構成のとき次のSQLを投げると。

select LEVEL,ID,NAME
from FAMILYTBL
start with ID = 1
connect by prior ID = PARENTID

[結果]
LEVEL  ID  NAME 
 1   1   与作 
 2   2   忠志 
 3   4   秀樹 
 2   3   慶子 
 3   5   翔 
 3   6   萌美 

と、ツリーっぽくクエリ結果を返してくれます。
注意点としてはレコードの中で特定の条件のみを対象としたい場合には
start withとconnect byのそれぞれに条件を記述必要があります。
※whereに書いても正しく動いてくれない。なぜ!?

select LEVEL,ID,NAME
from FAMILYTBL
start with ID = 1 and SEX = 0
connect by prior ID = PARENTID and SEX = 0

もしくはインラインビューにするですね。
12万件のテーブルでテストしましたけどコストはどちらも余り換わらないようです。
(ヒット件数が大量になると違ってくると思うけど、怖くてやってない)

select LEVEL,ID,NAME
from (select * from FAMILYTBL where SEX = 0)
start with ID = 1
connect by prior ID = PARENTID


階層の深さを制限する場合には次の様にLEVELに対して条件を付ければOK
このときはwhereで大丈夫。

select LEVEL,ID,NAME
from FAMILYTBL
where LEVEL < 2
start with ID = 1 and SEX = 0
connect by prior ID = PARENTID and SEX = 0

2006年08月17日

アップデート機能


モジュールアップデート機能を実装しようと調査したポイント

1.NTFSとFAT間でタイムスタンプがズレる問題
 
 モジュールのアップデートを実装しようとした時に
 どのファイルがアップデート対象であるか判断する必要がありますが、
 その最も(?)単純なのがタイムスタンプ方式だと思います。
 要するにローカルにあるファイルとサーバーのファイルのタイムスタンプを
 確認して、異なっていたらアップデートするって方式ね。
 
 実はこの方式には大きな落とし穴が・・
 なんとNTFSとFAT間ではタイムスタンプの持ち方が違うらしく
 全く同じファイルでも2秒ほどズレる場合があるのです。
 
 解決方法は・・・ズレを無視する!!!で良いのか!?

 参考
 http://support.microsoft.com/default.aspx?scid=kb;ja;JP402160


2.アップデートEXE自身をアップデートする
 
 なにかヤヤコシイ事しないと駄目っぽいけど
 次の手順で出来た。

 1) 旧モジュールが自身のファイル名を変更
  例 update.exe → __update.exe

 2) 新モジュールダウンロードし、正式なファイル名で保存

 3) 新モジュールを起動して、旧モジュールは終了
  このとき新モジュールの起動引数とかで旧モジュールのファイル名、プロセスIDを渡すと吉

 4) 起動された新モジュールが旧モジュールを削除
  起動引数で渡された旧モジュールを削除する。プロセスの終了を待った方が良いね。


 全ての環境で出来るかどうか疑問だけどXPとか2000では出来た。
 自EXEをロックするようなものだと駄目っぽいけど。

スクリプトでショートカットを作る

以下のコードを拡張子vbsで保存して実行すると
スタートメニュー内にフォルダを作って、その中に
ショートカットを作ります。


----------------------------------------------------------
Set fso = CreateObject("Scripting.FileSystemObject")
Set shell = CreateObject("WScript.Shell")

'AllUserの[全てのプログラム]へのパスを取得
sStartMenu = shell.SpecialFolders("AllUsersPrograms")

'フォルダを作成
sMenuDir = fso.BuildPath(sStartMenu,"Matsystem")
if not fso.FolderExists( sMenuDir ) then
fso.CreateFolder(sMenuDir)
end if

'ショートカットを作成
sSc1 = fso.BuildPath(sMenuDir,"XXXXXシステム" + ".lnk")
Set sc1 = shell.CreateShortCut(sSc1)
sc1.targetPath = "C:\Program Files\xxxxx\menu.exe"
sc1.WorkingDirectory ="C:\Program Files\xxxxx"
sc1.Save

----------------------------------------------------------

merge文の使い方

よく忘れるのでメモ

[テーブル間で追加、更新]
merge into USERTBL t
    using  USERTBL_UPD s
    on ( t.ID = s.ID )
    when matched then
        update set
            t.NAME = s.NAME,
            t.AGE  = s.AGE
    when not matched then
        insert (
            ID,
            NAME,
            AGE
        ) values (
            s.ID,
            s.NAME,
            s.AGE
        )


[更新対象を直接指定する]
merge into USERTBL t
using(select '1000' ID from dual) s
on (t.ID = s.ID)
when matched then
    update set
        t.NAME = '味噌カツ刑事',
        t.AGE  = 45
when not matched then
    insert (
        ID,
        NAME,
        AGE
    ) values (
        '1000',
        '味噌カツ刑事',
        45
    )

2006年04月19日

進捗管理ツール

なかなか便利そうなので、メモ
http://ganttproject.sourceforge.net/

2006年02月15日

Yahoo! UI Library

ちょっと凄かったのでメモ

http://developer.yahoo.net/yui/

2005年03月01日

CSSファイルにエンコード指定

メモ

CSSの先頭行に↓のような記述を追加

@charset "Shift_JIS";

2005年02月25日

ワークスペースを指定してEclipseを起動

メモ

eclipse.exe -data c:\xxx

2005年02月07日

JavaScriptでのポチ

同名のチェックボックスが大量にある場合にそのうち何個がチェックされているかを調べる場合 次のようにすると思いますが・・・
var chkcnt=0;
for(var i=0;i<document.form.delchk.length;i++){
   if(document.form.delchk[i].checked){
      chkcnt++;
   }
}

これで1万件とかにたいしてチェックすると5分ほど返ってきません。
要するに、javaスクリプトってのはポチ(ピリオドのことね)での参照が遅ーーいんですな。
下のように変更すると1万件でも30秒ほどで帰ってきます。

var chkcnt=0;
var delchk = document.form.delchk;
for(var i=0;i<delchk.length;i++){
   if(delchk[i].checked){
       chkcnt++;
   }
}

2004年09月10日

namespace stdでC2871

フリーのC++コンパイラ"Visual C++ ToolKit 2003"でも使ってみようかと思い、色々やっていたら
こんなエラー↓が発生

main.cpp(9) : error C2871: 'std' : a namespace with this name does not exist


なんで"std"が見つからないんだろ・・・


環境のせいかな??と色々もがいていたんですが解決せず、WEBを検索したらスグ解決。

#include <cstdlib>

でOKらしい。


BCCはこんなん無しでコンパイル通っていたんですけど、VC系はこんなん要るんですね・・

え?そうですか、常識ですか・・orz

2004年07月08日

Eclipse 3.0

Eclipse 3.0を導入してみました。

画面がかっこよくなってイイ感じです。
ただ、全体の動作は速くなった気がするのですが、エディタ部はいろいろ機能追加された為か若干重たくなった印象があります。
プラグインも動作しないものが多いですね、個人的には"SolarEclipse"が動作しないのは痛い・・

業務で使うにはもうちょっと環境が整うのを待った方がいいかもなんて考えています。

2004年04月14日

subversionって個人でイイ!

subversionってグループで使うのにもいいけど、個人で使う場合にスゴイ便利。
だってサーバーいらないんですよ!
サービス立てる必要ないんですよ!
(ローカルリポジトリでの場合ね)

個人でオンラインソフトとか開発してる人は是非とも導入してみてください。
仕事以外でソースいじるときって結構適当になりませんか?
で、「あ!!!!ヤベ!」ってことになりませんか?
そんな時にsubversionがあれば"なんとかなります"

2004年04月02日

Subversion導入

世間的にはバージョン管理ならCVSなんでしょうけど、windows環境との相性はいまいちですよね。
ということで、今やってる業務にSubversionってヤツをテスト的に導入してみました。

Subversionの動作にはApacheが無いとダメっていう誤解されてる人がいるみたいですけどそんなの要らないです。
svnserveという付属のプログラムを使えばネットワーク上で共有できます。
むしろApache使わないでsvnserveの方が簡単で、しかも速いです。
※ただしsvnserveは自身はNTサービスでは無いので、サービス化のラッパーが別途必要です。

で、使ってみたら、イイですよ。これ
日本語ファイルでもヘッチャラだし、バイナリでも安心。
リポジトリの設定とかもCVSに比べるととても簡単。
今のところ自分的には評価高いです。

ただ、欠点も・・
使えるGUIクライアントの種類が少ない(^^;
ほとんどの物が開発中の状態で、業務ではちょっと・・って感じのものばかりです。
唯一(調べた範囲内では)"TortoiseSVN"はよくできてます。
シェル拡張なので嫌いな人もいるでしょうけど、日本語化もされててわかりやすい。
エクスプローラー上でバージョン管理できるのでホント簡単ですよ。

-ポイントまとめ-

1.リポジトリの作成
 svnadmin create c:\SVNRepos\projX

2.サーバーの起動
 svnserve.exe -d -r c:\SVNRepos
 ※フリーウエアなどでサービス化することをお勧めします。

3.リポジトリへのURL
 svn://192.168.0.***/projX

4.リポジトリのアクセス権
 リポジトリ内のconfフォルダ内に"svnserve.conf"ってのがあるので修正

 [general]
 anon-access = none
 auth-access = write
 password-db = password.conf

 同じくconfフォルダ内に"password.conf"ってのを新規作成
 内容は↓ USERNAME = PASSWORD形式です。
 [users]
 mat = 4649
 yan = 5963

2004年01月27日

円と点の当たり判定

/*
 * 引数 r 円の中心点
 *      p 点の座標
 *      dHankei 円の半径
 * 戻り値 true:当たり- false:外れ-
 */
bool roundHitCheck(POINT* r,POINT* p,double dHankei){
    double dKyori  = sqrt(pow(r->x - p->x,2) + pow(r->y - p->y,2));
    return (dHankei >= dKyori);
}

点と三角の当たり判定

/*
 * 引数 p 点の座標
 *      p1,p2,p3 三角を構成する座標
 * 戻り値 true:当たりー false:外れー 
 */
bool triangleHitCheck(POINT* p,POINT* p1,POINT* p2,POINT* p3){
    int v1x = p->x - p1->x;
    int v1y = p->y - p1->y;
    int v2x = p->x - p2->x;
    int v2y = p->y - p2->y;
    int v3x = p->x - p3->x;
    int v3y = p->y - p3->y;
    
    int vn1 = v2x * v3y - (v3x * v2y);
    int vn2 = v3x * v1y - (v1x * v3y);
    int vn3 = v1x * v2y - (v2x * v1y);
    
    return ((vn1>0) && (vn2>0) && (vn3>0));
}

2004年01月22日

線分同士の当たり判定

線分mnと線分pqが交差するかチェックします。
bool chkLineLineX(POINT* m,POINT* n,POINT* p,POINT* q){
  double t,s,f;
  f = (n->x - m->x)*(q->y - p->y)
        - (n->y - m->y)*(q->x - p->x);
  if (f==0) return false;
        
  t = ((m->y - p->y)*(q->x - p->x)
        - (m->x - p->x)*(q->y - p->y))/f;
        
  s = ((m->y - p->y)*(n->x - m->x)
        - (m->x - p->x)*(n->y - m->y))/f;
                
                
  if ((t >= 0) && (t <= 1) && (s >= 0) && (s <= 1)){
      return true;
  } else {
      return false;
  }
                
};
※Delphiメーリングリストに投稿されていたコードをCに書き換えたものです。