폴리건에 버택스를 추가한다던지 같은 작업을 긴 라인동안 반복하게되면 나도 모르게 좀 깔끔하게 만들고 싶어진다.
// Sample , Ogre에서 ManualObject 설정하는 경우..
position( 0 , 0 );
textureCoord( 0 , 1 );
colour( 1 , 1 , 1 , 1 );
position( 1 , 0 );
textureCoord( 0 , 1 );
colour( 1 , 1 , 1 , 1 );
position( 0 , 1 );
textureCoord( 0 , 1 );
colour( 1 , 1 , 1 , 1 );
....
이럴때 같은 인자들을 묶고 다른것들만 넣어서
AddVertex( 0 , 0 , 0 , 1 );
AddVertex( 1 , 0 , 0 , 1 );
....
이런식으로 정리하고싶어진다.
정리하는 방법이 여러가지가 있는데 , 아에 AddVertex함수를 원래 클래스에 추가하는 방법이 있지만 , 엔진단에서 건드리는 경우가 될수도 있고 , 보통 로컬로 간단히 작업하는 부분이기때문에 요 파일 내에서 해결하는게 좋다.
일반적인 해결 방안은 전처리기( define )을 이용하는 방법이다.
#define AddVertex( x , y , u , v ) { \
position( x , y );\
textureCoord( u , v );\
colour( 1 , 1 , 1 , 1 );\
}
이걸로 정리가 가능하다.
만세
라고 생각하면 오산..
개인적으로 define을 싫어한다. 디버그할때 구체적인 에러위치 파악하기가 어렵고 , 특히 이런 define을 이용한 펑션처럼 구현하는걸 꺼린다. 쓸수있다면 inline을 쓰고 싶다.
inline void AddVertex( float x , float y , float u , float v )
{
position( x , y );
textureCoord( u , v );
colour( 1 , 1 , 1 , 1 );
}
오 아름답다. 하지만 큰 문제가 있다. 컴파일하면 에러가난다.
'AddVertex' : local function definitions are illegal
C++ 에서 펑션 내부에 펑션 정의를 허용하지 않는다. 왜 인라인도 안되냐고.
결국 이 인라인 펑션을 글로벌로 빼야하는데 , 어차피 일부분에만 사용하는 펑션을 글로벌로 빼는 것이 영 탐탁치 않다. 어떻게든 안에서 해결하고 싶다.
Try One
핵심 아이디어는 펑션 내부의 함수 선언은 불가지만 스트럭쳐나 클래스 선언은 허용된다는 점이다. 즉 , 스트럭쳐를 선언하고 그 내부에 펑션을 만들어서 사용하는것이 가능하다는 소리다.
코드의 간편화를 위해 만들고 싶은 펑션을 아래걸로 생각하겠다.
void Function( int n )
{
printf( "%d\n" , n );
}
클래스의 맴버 펑션으로 구현을 우선 해보면
struct Function
{
void Do( int n ) { printf( "%d\n" , n ); }
};
대충 이렇게 구현이 될텐데..
사용법은 2가지다.
Function fun;
fun.Do( 1 );
or
Function().Do( 1 );
둘다 그다지 아름답지 않다 -_-.
이미 원하는 펑션의 이름이 있으므로 중복해서 네이밍을 해야하는것이 눈에 띄고 무엇보다 길고 괄호가 많아서 짜증난다.
Try Two
static function을 이용하면 조금(?) 간소화가 가능하다.
struct Function
{
static void Do( int n ) { printf( "%d\n" , n ); }
};
사용은
Function::Do( 1 );
그나마 조금 낫다. -_-
Try Three
그러나 내가 원하는건 딱 Function 으로 실행을 하는건데... 여기서 전처리기의 도움을 살짝 받으면 조금 나아진다.
#define FunctionFunction::Do
Function( 1 );
오오 된다.
Try Four
Static펑션을 사용하는 불합리함이 있으므로 저방법도 되긴하나 그다지 만족 스럽지 않다. 가능하면 내부에서 모든것을 해결하고 싶다. 그래서 operator() 를 이용한 방법을 써봤다. 개인적으로 펑션 포인터를 사용하는 구조 대신 이 operator() 를 이용하는걸 좋아한다.
struct Function
{
void operator()( int n ) { printf( "%d\n" , n ); }
};
사용법은
Function a;
a( 1 ); // ok
Function()( 1 ); // ok
// Function( 1 ); // ERROR
인스턴스화를 하지 않으면 펑션을 사용하지 못하는 단점 , 그리고 두번째 호출방식은 괄호가 중복으로 들어가는 단점이 있다.. 이걸 Try Three 방식을 적용해서
#define FunctionFunction()
사용
Function( 1 )
오 -_-;; 되긴 된다.
전체적으로 정리해서 보면
struct Function
{
void operator()( int n ) { printf( "%d\n" , n ); }
};
#define Function Function()
......; 해결은 됐는데 그다지 아름답지 않다 -_-;... 뻘짓은 계속!
Try Five
번쩍 떠올랐따. 니미 ; 생성자 이용하면 더 간단하잖아!
struct Function
{
Function( int n ) { printf( "%d\n" , n ); }
};
Function( 1 );
오오 간단하다. 하지만 만약 리턴값이 필요한 경우라면 사용 할 수가 없다. 리턴값이 필요 없는 경우라면 이걸로 덕질을 종료할 수 있는 상황이지만.. 리턴도 받아야 돼!
Try Six
두 인자 더해서 리턴하는 함수로 예제를 바꾸자
int Add( int left , int right )
{
return left + right;
}
자자 리턴을 받을려면 어떻게 해야할까.
잠시고민 하다가 내린결론 , Type Casting Operator Overloading.
struct Function
{
typedef int RETURN_TYPE; // Generic Programming!!
Function( int left , int right )
{
nReturn = left + right;
}
operator RETURN_TYPE() { return nReturn; }
RETURN_TYPE nReturn; // 리턴값
};
int a = Function( 1 , 2 );
와 되긴 됐다. orz;;
이게 뭥미;;
결국 나만 알아보는 코드가 만들어져 버렸다. -_-;;;
자자 -_-;; 하는김에 좀더 해보자! 뻘짓 뻘짓
Try Seven
내친김에 InFunction의 베이스 클래스도 만들어보자. Type Casting Overloading을 베이스 클래스에서 처리해 보자 라는 데서 스타트..
virtual Ret Do( Param1 left , Param2 right ) = 0; // Pure Virtual Function
operator Ret() { return mReturn; }
protected:
Ret mReturn; // 리턴값
};
아싸 거창하다. 여차하면_인자_갯수만큼_베이스클래스_만들_태세.jpg
그리고 펑션 내부에서 사용은
struct Function : public InFunctionModule< int , int , int >
{
int Do( int left , int right )
{
return left + right;
}
};
int a = Function( 1 , 2 );
아싸 뭔가 그럴싸하다. 그런데 안된다. -_- Function 에서 InFunctionModule로 생성자 인자 전달이 자동으로 되지 않는다. 그리고 그렇다 하더라도 큰 문제점이 하나있다. 프로그램 좀 해본 사람이라면 바로 눈에 들어올 듯. Pure Virtual Function을 Base Class의 Constructor 에서 호출하는 오류는 범했다. ( Effective C++ 참조 )
Try Eight
Try Seven의 문제를 해결해봤다. 결국 캐스팅하는 부분만 남기고 나머진 다 대피.
template < typename Ret >
struct InFunctionModule
{
typedef Ret ReturnType;
void Return( ReturnType r ){ mReturn = r; }
operator ReturnType() { return mReturn; }
protected:
ReturnType mReturn; // 리턴값
};
사용하는 곳은
struct Function : public InFunctionModule< int >
{
Function( int left , int right )
{
Return( left + right );
}
};
int a = Function( 1 , 2 );
오오 ... 이런 나중에 나도 못 알아볼 코드 같으니 orz
Conclusion
프로그램은 누가봐도 눈에 잘 들어오게 짜는게 장땡이라고 생각한다.
그래서 이런 뻘짓은 제가 한걸로 충분하니 하지 마시고 -_-;
그나마 여기서 쓸만한 결론은 Try Five 밖에 없는거 같다.
어차피 로컬로 내부의 문제만 어떻게 짜든 무슨 상관이랴 -_-; 개중에 제일 깔끔하다.
펑션내부에 펑션은 C내부 구조적인 문제때문에 허용을 하지 않는다고 알고 있는데 , 스트럭쳐가 허용이 되는거면 굳이 막아둘 필요도 없지 않나 란 생각도 든다.
Magic
the Gathering Online v3 ( 이하 MTGO )용 유틸리티로 , 원래 클라이언트에서 한글을 지원하지 않습니다.
그래서 한국 사람은들은 편법으로 노트패드에 한글로 적고 alt+tab으로 옮겨서 카피해 넣기를 반복하면서 한글로 채팅을하고 있는
현실이죠. 그걸 조금이라도 개선하기 위해서 만든 프로그램입니다.
즉. MTGO에서 한글입력을 가능하게 해주는 서드파티입니다.
어떻게 사용하나요?
우선 MTGO클라이언트를 실행하고 같이 HanMTGO를 실행해주시면 , 알아서 달라붙은다음에 창이 사라집니다. 그뒤로 어떤 차이도 없습니다. 단지 한글입력이 됩니다. 그냥 한영 전환해서 한글 입력을 하시면 됩니다. 참고로 게임중에 나오는 창에선 한글이 깨집니다. 주의하세요. 아 그리고 중요한거 , 구현 구조상 현재 2벌식 한글만 지원합니다. 3벌식 쓰시는분껜 죄송합니다.;
그리고 예민하신 분들을 위해. 이 프로그램은 레지스트리도 건드리지 않고 , 다른 파일을 생성하지도 외부와 연결을 시도하지도 않습니다. 안심하고 쓰세요
이건 공짠가요?
네 개발자 취미로 모두가 조금이라도 편해졌으면 하기에 만든것이므로 무료입니다. 하지만 재배포는 허락하지 않습니다. 반듯이 이 홈페이지 URL로 등록해주시기 바랍니다. 간혹 업데이트가 있을수 있으므로 이건 지켜주세요.
그리고 이걸로 정말 편해졌다. 조금더 개선해주길 바란다.. 이런 생각이 드시면 개인적인 기부 환영합니다. ㅠㅠ; 매온 Tix로 받습니다. ( 과연 누가 할것인가 -_-;; ). 아님 안쓰는 카드 저에게 좀 버려주세요. 매온 아이디 'magoja' 입니다.
만든 사람은 뭐하는 아저씨인가요?
그냥 매직을 좋아하지만 , 돈이 없어서 펑펑 지르진 못하고 , 13년째 주위만 뱅뱅 맴도는 방랑자입니다. 본업은 게임 프로그래머 ( 3D )이고 조그마한 벤쳐기업에서 온라인 게임을 제작하며 대박을 꿈꾸고 있습니다.
더하실 말 없나요?
구현 구조상 입력이 안되는 글자라던가 사소한 버그가 있을 수 있습니다. 발견되면 재현방법과 함께 글을 남겨주시기 바랍니다. 그리고
보다 나은 프로그램을 위한 아이디어도 환영합니다. 그리고 즐겁게 즐겨주세요. 그동안 답답했던 매온 채팅환경이 조금이라도 나아졌길
바랍니다.
우
선 생각은 아침에 문득 , 키보드 후킹을 통한 입력을 이용해서 지금의 Copy&Paste작업을 없엘 수 있지 않을까에서
였다. 3년쯤전에 Trader를 만들어볼까 하고 Socket Hooking이랑 Keyboard Hooking자료를 좀 구해놓고
테스트까진 했었는데.. 그 예제를 다시꺼내서 우선 매온에서 키보드 입력을 받을 수 있는지 부터 확인했다.
하지만 키보드 후킹은 매온에서 막혀있는듯하다. 후킹은 성공하지만 어떤 메시지도 오지 않는다. 그래서 일단 방향을 선회해서 직접적인 윈도우 메시지를 받는 법을 사용했다.
DLL
Injection으로 , 매직클라이언트의 프로세스 내로 침투해서 , FindWindow로 윈도우 핸들 얻은다음에 ,
GetWindowLong & SetWindowLong 으로 WndProc를 바꿔치기 , 윈도우가 받는 모든 메시지를
중앙통솔할수있게 되기 땜에. 거기서 직접 클라이언트로 Paste메시지를 보낼 수 있으면 외부에서 클립보드를 세팅해서 원하는
스트링을 집어넣는게 가능할거란 생각이 들었다.
그래서 클립보드 예제를 뒤져보니까. Paste할때 WM_PASTE메시지가 간다는데.. 그래서 PostMessage해보니....니미 - -... 왜 안돼
결국 삽질끝에 WM_CHAR메시지에 22 ( 0x16 )키의 정보가 가면 클라이언트 내부에서 Paste를 수행하는것을 발견. 클립보드에 데이타 세팅하고 클라이언트로 페이스트 메시지 보내는 것에 일단 성공.
그뒤론 사소한 노가다들 -_-;;;;
특히 저 완성형 변환 테이블이 완전한게 아니라서.. 안나오는 글자를 발견할때 마다 Case by Case로 코드를 추가했다.
여튼 필요로하던 유틸을 직접 만들어서 기분이 좋음.
아쉬운점은 IME_COMPOSIONG을 보여주질 못한다는건데.. 이것도 기술적인건 다 알고 있으니까 조금만 노가다 하면 될거 같은데.. 담에 시간나면 하지 뭐.. (기부하는 사람있으면 좀더 생각해보고 - -;; )..
개발 시간은 한 5~6시간 정도 -_-;;
추가로 조합형 출력을 위해서 퍼온 한글 라이브러리를 개조해서 , 완성된 글자가 나오면 그만큼 키보드 버퍼를 날리는 방식으로 개조하고 , 화면에 출력되는건 그냥 찍은다음에 조합글자를 지우는 방식으로 구현.. (완존 꼼수)
2009/09/25
패치되면서 하드코딩된 윈도우 네임때문에 못찾던 버그수정.."Magic Online v3" 까지만 검색해야하는데 런쳐에서는 그렇게 해놓고 DLL안에서 안하는 -_-.. 정신줄 놓은 시츄에이션.
어차피 안되니까 다들 새로받아야할테니 이기회에 입력 오류생기던걸 좀 손봤는데..
매온 클라이언트에 케릭터메시지가 버퍼링되면 무시해버리는 기능이 있는지 , 연속으로 보내면 처리가 안된다. 그래서 블러킹되는 메시지는 큐잉해서 순차적으로 처리하게 하긴 했는데... 문제는 순차적으로 해서 글자를 보내도 빠지는게 가끔 생김.. 그냥 좀 불편하지만 고고싱 해야하지 않을까함..지금 구조상은 이정도 까지가 한계인듯.
클라이언트 내부에서 글자를 렌더링 하는 루틴을 찾아서 개조하는 방법도 있는데 , 이건 좀 노가다가 심해서 안할듯..
2009/10/17
Zendikar 나왔는데 , 돈없어서 손가락만 빨다가 .. 문득 기존부터 계속 속썩이던 글자 빠지거나 겹치는 문제가 떠올랐는데.. 그 구조 자체가 클립보드를 이용한 전송이었기때문에 생기는 구조적인 문제임을 발견..
그럼 다른데선 어떻게하지?.. 그냥 WM_CHAR로 못보내나?
Spy를 사용해서 메시지를 들어가는걸 보니 , 멀티바이트를 순서대로 보내면 알아서 조합이 되나보다. 니미 ;; . 코드 테스트 해보니까 확실. 그래 이거다.
void SendStringWithWM_CHAR( HWND hWnd , const char * p )
{
int nLen = strlen( p );
for( int i = 0 ; i < nLen ; i ++ )
{
char nChar = p[ i ];
DWORD dw = 0;
char *pDW = ( char * ) &dw;
근데 글자가 깨진다. 왜이런지 해결하는데 5시간 걸림.
결국, Unicode모드에서 MBC모드간에 차이로 결론이 났다. PostMessage에서 WM_CHAR로 넘어가는 메시지는 그 코드셋에 따라서 변경이 생긴다는 사실을 아는데 5시간이 .. 털썩..
이거 해결할려고 따로 메지시 만들어서 포워딩하는것까지 하는 삽질을 했었음..
단지 프로젝트 설정문제임이 밝혀져서.. 2시간에 끝날일이 7시간걸려버렸음.. 젠장;;
어쨌든,, 가끔 있을 업데이트를 위한 버젼 확인 기능 추가..
homepage 위에다가 주석으로 버젼 기입해놓고 그걸 읽는 방식을 사용함.
이름 : MtgImage ver 2009/07/13 제작 : 마고자 용도 : Magic the Gathering 카드이미지를 magiccards.info 사이트에서 긁어주는 것
(주로 Magic Work Station , MWS에서 사용하는 용도 )
사용법 :
프로그램을 실행하고 원하는 익스펜션을 선택하고 Get Images 버튼을 누르면 순서대로 다운 받는다.
양에따라 상당한 시간이 걸릴수 있으니 참고.
파일은 익스편션 네임을 폴더로 해서 카드 이름으로 저장이 된다. 밑의 "Save with CardNumber" 가 선택된경우는 카드 번호로 저장된다. 혹시나 유니코드 문제로 파일이 제대로 저장이 되지 않는 경우가 있을수 있는데. (ex AEther Flash 등등 ) 그런 경우 이용하면 좋다.
스타트는 맹목적인 프로그래밍 공부는 너무나 지루하고 효율이 안난다는것 , 역시나 사용해보지 않으면 랭귀지를 내것으로 만들기 힘들다. 그래서 구상. 대체 뭘 만들면 연습도 되고 좋을까. 파이썬의 특징인 간편한 스트링처리를 활용해서 기본적인 UI를 갖춘 Image Downloader를 만들자 로 시작했다.
기존 VC로 만든것과 다른점은
전엔 익스펜션정보를 외부파일에 놔두고 그걸 이용해서 데이타를 긁었다.
하지만 이번엔 익스편션 정보와 카드 정보들을 모두 해당 사이트에서 긁어서 보여준다. 그래서 익스펜션 추가되더라도 프로그램이 바뀌는 것이 없다 <= 뽀인트
물론 현재 Magiccards.info 사이트의 기본 프레임웍이 바뀌면 안될 수 있다
작업환경은 Python 2.6 + Eclipse with Python plugin. 초반에 이클립스 몰라서 노트패드로 졸 고생 -_- 이런거 있으면 미리미리 알려주길 바람 .. UI는 wxPython 을 이용해서 처리하고 다운받을때는 Dialog 창에서 다운로드 Thread 를 돌린다. 실행화일은 Py2exe 로 빌드했다.
누구 보여주기 부끄런 소스는 여기 있다. 물론 무단 도용은 금지. 사용할땐 허락을 요구함. 보면 알겠지만 , 기술적으론 특별한것없고 , html파일 뒤적여서 원하는 정보만 뽑아내는 string 노가다의 결과물.
파이썬이 참 생산적이고 좋은 언어라는 것을 작업하면서 느꼈다. C++ 같은 클래스 상속개념도 있어서 금박 적응 했다. 새로운 문법 새로운개념들 모두 재미있고 이런것도 C++에 있으면 좋겠다 라고 생각되는것들도 종종있다. 앞으로 간단한 어플리케이션은 대부분 Python으로 만들듯하다. 역시나 생산력엔 장사없다. C++은 코어쪽 루틴 작업할때 중심으로 쓸듯.
파이썬으 Embed에서도 좋은 성능을 낼수 있으면 좋겠지만 , 그렇진 않은듯하다.
실제로 그렇다면 Lua 같은 embed에서 강한 언어가 나오지 않았겠지.
앞으로 업데이트가 있을까?.. 나도 모름
원래 만들던 목적은 , 저렴하게 매직을 즐기기위한 온라인 드래프트 프로그램인데 -_-; 그거에 가장 기초작업으로 진행한것임.. 천천히 공부하면서 만들어봐야지.
Update Log
2009/07/13 초기 버전 배포
2009/07/16 사이트 접속이 안될때 에러 처리 추가
2009/07/16 파일명 끝에 ".full" 넣어주는 옵션 추가 ( MWS 용 )
2009/07/22 Split card의 '/'를 제거함. 그리고 IO에러 발생시 로그를 남김.
PS> Feedback 은 이글의 리플로 부탁드립니다. PS2> Magiccards.info 사이트에서 M2010 업데이트가 되는대로 다운이 가능할거예용.. PS3> Magiccards.info 싸이트가 접속이 안되면 에러가 납니다. 안되면 직접 사이트 들어가보세요
- C++에서 NULL에 해당하는 키워드는 None 이다.
그리고 실제 널인지 확인하려면 type을 활용한다.
type( nodeChild ) == type( None )
파이썬은 데이타가 모두 동적이기때문에 , 간혹 이게 어떤건지 확인할때 type은 유용하다
- Enum 이 따로 없다. 하지만 Enum을 쓰는 대신에 그냥 스트링을 처리하면 보기에도 편하다. 글자가 틀리면 대략 난감.. .. 어차피 switch - case 문이 없어서 if elif 페어로 계속 넣어야 하니까 대충 적응하자.
- string 모듈의 strip() 펑션은 스트링의 화이트 스페이스를 제거해준다.
>>> from string import *
>>> strip( ' a ')
'a'
>>> strip( ' \n' )
''
- Tuple에 익숙해지자.
파이썬은 리턴값이라던지 모든 데이타에 Tuple을 적용할수 있다. 함수에서 여러개의 인자를 리턴하면 ( return a , b ) 리턴값은 계네들이 합쳐진 튜플로 넘어온다. ( [ a , b ] ) 그래서 잘 짤라서 쓰는 방법이 있고 임의로 튜플을 만들어서 리턴할 수도 있다.
Magic Work Station 이라고 불리는 Magic the Gathering 이란 트레이딩 카드 게임을 온라인상에서 무료로 할 수 있는 프로그램이 있다. 이걸 만든 업체쪽에선 Wizard( 매직더게더링 원 저작권 업체.. )에 어떤 커미션도 제공을 하고 있는 것이 아니기 때문에 , 매직 게임 자체에 대해 어떤것도 넣을수가 없기때문에 , 그 게임을 할 수 있는 프레임만 제공한다. 카드 DB같은경우도 저작권에 걸리기 때문에 다른형식으로 공급하는데 .. 어쨌든 그렇게 비공식적으로 사용하는 것이기에 매직 카드 자체의 매력인 카드 이미지조차 제대로 제공돼지 못한다.
어디서 모아놓기도 그렇고 누군가 퍼다주기도 귀찮고 ..
그래서 사람마다 다른 카드 이미지를 가지고 있다. 어떤사람은 용량 적은걸로 , 어떤사람은 풀이미지로..
개인적으로 풀이미지를 무척 가지고 싶어했었는데 , 다음카페 매직동호회에서 '오영석'씨 께서 풀이미지를 구할수 있는 웹사이트에 대한 정보를 흘렸다. 찾아보니 http://magiccards.info 라는 카드 검색 사이트인데 , 여기있는 카드이미지가 가히 일품!. 이분께선 그걸 하나하나 검색해서 저장했다고 한다... 카드 검색하고 클릭하고 이미지보고 다른이름 저장하고...이걸..몇백장... -_-;;
그걸 보고 생각이 났다. 정의감에 타올랐다.
'저거 프로그램으로 만들면 그냥 쫙 받을텐데 -_-'
일도 하기 싫은데 농땡이 치면서 만들어볼까?.. 하고 시작한 프로젝트 ..;
요는 , magiccard.info 에서 원하는 카드 이미지를 익스펜션 셋별로 긁어다가 mws포멧으로 저장해주는 프로그램이다.. 라고 할수 있겠다.
우선 사용한 컴파일러는 Visual Studio 2005 Professional , MFC를 이용한 Dialog base 프로젝트로 시작했다. 간단한 프로그램 만들기엔 제일 좋은 구조. 어쨌든 대충 머리에 그리기를 .. 첫화면에선 다운로드 받을 익스펜션을 선택하면 될거같고.. 그리고 Download 버튼이 있고 누르면 새창이 뜨면서 프로그래스 바가 진행이 되면서 하나씩 다운 받는걸 생각 했다.
여기서 필요한 기술. MFC UI프로그래밍을 제외하고 ... 1,http 프로토콜을 이용해서 파일 저장.
2,위의 파일 저장작업을 Back thread로 처리
3,확장성을 위한 익스펜션의 스크립트화
음 2,3이야 하기가 귀찮아서 그렇지 늘상 하던 작업이기 때문에 어려울것이 없을거 같고 .. 작업을 시작할땐 1번이 문제였는데 .,.. 그냥 GetHttpFile( "url" , targetfile ) 해서 뚝딱 하고 떨어지는 함수를 누가 만들어주면 참 쉽겠지만 -_- 세상을 그렇게 날로 먹지 못하는 법이다. 검색검색 .. 아 이런함수가 있군 -_-;; google을 한 10분쯤 뒤지니까 http프로토콜을 이용한 스트링 출력하는 소스를 발견했다.
다행히도 magiccard사이트는 파일을 카드 이름으로 하지 않고 번호로 해두었기때문에 자동화가 가능했다. 단순히 익스펜션 심볼 (bok) 그리고 카드가 몇장이 있는지 알면 해당 익스펜션을 모두 다운 로드 받을수가 있는 것이다.
근데 문제는 이렇게 받은게 무슨카드인지 모른다는 건데.. 즉 번호->카드 이름을 바꿔줄 인터페이스가 필요했다. 처음에는 이걸 테이블로 만들 생각을 했는데..
bok,163,Umezawa's Jitte
bok,164, .....
.....
매직에 익스팬션이 좀 많다. 저걸 언제 손으로 다해 -_-;; 그래서 고민고민 하다가.. 이 정보 마저도 Magiccard.info 사이트에서 퍼오기로 했다. 저 이미지를 표시하는 웹페이지 http://magiccards.info/bok/en/163.html
이 주소를가지고 html파일을 분석해서 타이틀 태그에서 카드이름을 뽑아내기로 했다.
간단한 스트링 처리로 테스트 성공.
이제 한셋을 다운 받는데 1,익스펜션 심볼
2,해당 익스펜션의 카드 장수
3,MWS사용하는 심볼 ( 저장용 )
이것만 있으면 가능해졌다.
이 정보는 여러글을 참고해서 노가다로 정리해서 스크립트로 만들었다. http://magoja.com/expension.txt
그리고 이 스크립트 역시 서버에서 저장을 해서,
exe파일과 같이 옮겨다니고 , 매번 업데이트해야하는 귀찮음을 없엤다.
그리고 -_-;; 이게 다운로드를 하고 있으면 윈도우가 메시지를 못받는 비동기식이기때문에 다운로드를 백스레드로 돌리지 않으면 만족할만한 UI 를 뽑아 내기가 어려웠다. 처음에 프로토타입은 그런거 전혀 무시한채로 만들었는데 , 어차피 한번 귀찮으면 끝나는 문제이기 때문에 작업을 마무리 지어서 마무리 버젼을 제작했다.
뭐 나머지는 자잘한 UI작업들이기때문에 ( 하지만 대단히 중요한 -_- )
따로 설명은 하지 않겠지만 , 대충 이러이러 하여 프로그램이 완성이 됐다.
참 오랜만에 이런 유틸리티를 만들었다. 버쳐파이터 대진표 역계산 프로그램 MagFa 만든이후로 더 만든게 있던가 -_-?.. 야튼 대충 마무리 돼서 기분이 좋다.
총 제작기간 이틀 -_-; 회사에서 농땡이 치면서 ;
야튼 MWS쓰는 사람들에게 많이 도움이 됐으면 좋겠다.
Update Log 2007/06/01
- 같은 이름의 카드 넘버링 추가. ( ex Mountain (2) .. )
2007/05/31 ver 1.0b 배포
- 백스레드 처리 , UI 처리
- 모든 익스펜션 적용.
- TSB 블럭 처리.
- Split Card 처리 추가
- AEther 글자 처리.. ':' 처리 (COP)
좀 매니악한 키보드를 샀더니 좋으면서도 한편으론 , 회사에서 사용하는 컴퓨터가 많아서
(노트북 까지 포함해서 3대) 바뀐 키보드는 한대 뿐이고 , 그렇다고 키보드를 3대를 사서 놓을
수도 없고 많이 고민을 하다가 KVM ( Keyboard , Video , Mouse 공유 장비 )를 알아보다가
이것도 해결책이 아닌거 같아서 조사중에 SourceForge란 오픈소스 프로젝트인 Synergy란
키보드 마우스 공유 프로그램을 발견했다.
이 프로그램은 , 한자리에서 여러대의 컴퓨터를 사용할경우 키보드와 마우스를 소프트웨어
적으로 공유하는 프로그램이다.
즉 , 사진처럼 화면이 3개 , 컴퓨터가 3개인데 키보드 마우스는 하나로 모두를 컨트롤 하는것이다.
방법은 마우스 커서가 컴퓨터와 컴퓨터 사이를 넘어다니고 , 마우스 커서가 있는 컴퓨터에
키보드 입력이 들어가는 것이 이 프로그램의 핵심적인 아이디어.
참 감동해서 사용을 했으나. 결정적인 단점이 있었다.
이게 미국에서 만든 프로그램이다보니 다국어 지원이 전혀 안돼어 있다는 것 ..;
즉 한영 전환이 돼지 않았다! -_-;;
야튼 오픈 소스의 장점을 이용해서 프로그램을 뜯어보다가. 해당 키 처리가 돼지 않는 것을
발견하고 소스를 고치다가 귀찮아져서 던져놓고 검색을해보니 역시 누군가 열심히 작업한
결과물들을 찾을 수 있었다 ( 구글신 만세 ) 야튼 여러사람의 노하우를 종합해서 빌드를해서
지금 쓰고 있다.
결정적인 문제점이 Shift+space가 넘어가지 것이었는데 , 이게 해결돼서 비싼 해피해킹을
2대나 추가적으로 사야하는 갈등에서 해결돼서 오늘 기분이 너무 좋았다.
프로그램 설정이 처음에 조금 까다로웠는데 ,
개념을 살짝 이해하면 그다지 어렵지 않고 한번 하면 끝난다.
어쨌든 고친 바이너리와 참고자료를 다음 링크에 남겨두겠다.
필요한 분들을 참고하기 바란다.
아 참고로
1, 고정 IP를 가지고 서로에게 억세스를 할수 있는 시스템이 필요하고
2, 어차피 소프트웨어적인 것이기때문에 부하가 걸리거나 훅이 걸리는경우
키 입력을 전송할수 없는 경우가 발생한다.
하지만 프로그램을 무지 잘만든건 여러가지 편의기능을 제공한다는거. 1, 컴퓨터간에 클립보드 공유까지 지원하고 ,
2, 부팅시 자동 실행 설정등 아주 깔끔하게 돼어있다.