블로그 이미지
초딩입맛제주아재
하고 싶은 것만 하며 살고 싶다

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
2006. 10. 13. 11:19 Programing/PHP

server.php

set_time_limit(0);

define("_IP",    {IP});
define("_PORT",  {PORT});
define("_TIMEOUT", 10);

$cSock = array();
$cInfo = array();

$sSock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_bind($sSock, _IP, _PORT);
socket_listen($sSock);

while(1)
{
  $sockArr = array_merge(array($sSock), $cSock);

  if(socket_select($sockArr, $tWrite = NULL, $tExcept = NULL, _TIMEOUT) > 0)
  {
       foreach($sockArr as $key => $sock)
       {
           // Listen 하고 있는 서버 소켓일 경우
           // 새로운 클라이언트의 접속을 의미
           echo $sock.'/'.$sSock."\n";

           if($sock == $sSock)
           {
               $tSock = socket_accept($sSock);

               socket_getpeername($tSock, $sockIp, $sockPort);

               $cSock[$tSock] = $tSock;
               $cInfo[$tSock] = array('ip'=>$sockIp, 'port'=>$sockPort);

               msg("client connect : ".$sockIp.":".$sockPort."\n");
           }
           // 클라이언트 접속해 있는 소켓중 하나일경우
           // 해당 클라이언트에서 이벤트가 발생함을 의미
           else
           {
               $buf = socket_read($sock, 4096);

               // 접속 종료
               if(!$buf)
               {
                   exceptSocket($cSock, $cInfo, $sock);
                   msg("client connection broken : ".$sockIp.":".$sockPort."\n");
               }
               // 메시지 수신 이벤트
               else
               {
                   msg("recive data : ".$buf."\n");

                   $thisSockInfo = $cInfo[$sock];
                   //$cmd = substr($buf, 0, 4);
                   $cmd = $buf;

                   switch($cmd)
                   {
                       // 시간전송
                       case "time":
                           msg("client(".$thisSockInfo['port'].") time data request\n");
                           socket_write($sock, date("Y/m/d H:i:s"));
                           break;

                       // 종료
                       case "quit":
                           msg("client(".$thisSockInfo['port'].") quit request\n");
                           socket_write($sock, "quit");
                           socket_close($sock);
                           exceptSocket($cSock, $cInfo, $sock);
                           break;
                       default:
                           if(substr($cmd,0,1) == ':'){
                               msg("client(".$thisSockInfo['port'].") sendmsg : ".substr($cmd,1)."\n");
                               broadCasting($sockArr,$sock,substr($cmd,1));
                           }else{
                               msg("client(".$thisSockInfo['port'].") invalid command $cmd\n");
                           }
                           break;
                   }
               }
           }
       }
  }

  $i++;

}

function exceptSocket(&$sockSet, &$infoSet, $sock)
{
  unset($sockSet[$sock]);
  unset($infoSet[$sock]);
  // array_merge 함수에서 error 발생을 막기위한 처리
  if(count($sockSet)==0)
  {
       $sockSet = array();
       $infoSet = array();
  }
}

function msg($msg)
{
  echo "SERVER >> ".$msg;
}

function broadCasting($socks,$cSock,$msg){
  global $sSock;

  foreach($socks as $key => $sock){
       if($sock != $sSock && $sock != $cSock){
           socket_write($sock,$msg);
       }
  }
}

client.php

define("_IP",    {IP});
define("_PORT",  {PORT});

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_connect($sock, _IP, _PORT);

msg("socket connect to "._IP.":"._PORT."\n");

while(1)
{
  msg("Enter command time or quit : ");

  // 사용자의 명령어를 입력받습니다.
  $stdin = ereg_replace("\n|\r", "", read_data());
  //$stdin = substr($stdin, 0, 4);

  // time 또는 quit 메시지 말고는 무시 합니다.
  if($stdin == "time" || $stdin == "quit")
  {
       msg("Input command : ".$stdin."\n");
  }else{
       if(substr($stdin,0,1) == ':'){
           msg("sendmsg : ".$stdin."\n");
       }else{
           msg("invalid command (not send). If you want said ':' and your message.: ".$stdin."\n");
           continue;
       }
  }

  socket_write($sock, $stdin);
  $sMsg  = socket_read($sock, 4096);

  if(substr($sMsg, 0, 4) == 'quit')
  {
       socket_close($sock);
       exit;
  }else
  {
       msg("recived data : ".$sMsg."\n");
  }
}

// 표준입력을 받아 값을 리턴하는 함수
function read_data()
{
  $in = fopen("php://stdin", "r");
  $in_string = fgets($in, 255);
  fclose($in);
  return $in_string;
}

// 로그 출력
function msg($msg)
{
  echo "CLIENT >> ".$msg;
}

단방향 채팅프로그램이다...-_-;
서버에 지정된 명령어에 의해 클라이언트의 메세지를 처리해주는 정도...
다중 클라이언트 접속이 허용되지만
클라이언트간 메세지 교환은 이루어지지 않고
클라이언트 대 서버의 통신만 가능하다.
서버에서 클라이언트의 메세지를 전체 클라이언트에게 뿌려주는
브로드캐스팅 구현이 안됐다...



TODO:
1.서버의 브로드캐스팅을 구현해야 실질적인 다중채팅이 이루어진다.
2.서버에서 임의의 메세지를 전송 하는 기능을 구현해야 한다.

'Programing > PHP' 카테고리의 다른 글

[OSX] Eclipse에서 PHP 로컬 개발/테스트 환경 구축하기  (4) 2008.08.30
Enabling PHP and Apache in Leopard  (2) 2008.08.19
WAV파일 분석  (0) 2006.11.10
간단한 대화식 프로그램  (0) 2006.07.24
시스템 모니터링 툴  (0) 2006.07.17
posted by 초딩입맛제주아재
2006. 10. 11. 11:00 Programing/Smalltalk
1. Shell 클래스 아래 HouseKeepingBookShell 클래스를 만듭니다.(이것은 MVP에서 P인 Presenter에 해당합니다)

Workspace에서 HouseKeepingBookShell showOn: testBook 을 실행해 봅니다.


창이 새로 열리죠? 그것을 캡쳐해서 올려주세요.






2. Class Browser의 클래스트리에서 HouseKeepingBookShell 의 팝업메뉴 View... / New를 합니다. (이것은 MVP에서 V인 View에 해당합니다) 이름은 그냥 기본으로 있는 Default View로 엔터누릅니다. View Composer가 열렸죠. 1번 문제에서 봤던 창이 있을 겁니다. 이 창을 편집한다는 소리죠. View Composer로 왼쪽에 뷰툴박스를 열어서 ListPresenter.Default View를 찾아 이 창에다 추가해줍니다.(끌어다놓기하면 됩니다) 오른쪽 하단의 속성창에서 name이라는 항목을 찾아 문자열로 book list 라고 이름 지어줍니다. View Composer를 저장하고 닫습니다.


Workspace에서 HouseKeepingBookShell showOn: testBook 을 실행해 봅니다.


창이 새로 열리죠? 그것을 캡쳐해서 올려주세요.


/



3. HouseKeepingBookShell 에 items라는 객체변수를 만듭니다. createComponents라는 매쏘드를 검색(Definitions of...)해 봅니다. 그 매쏘드들을 보고 흉내내서 ListPresenter를 만들어 items변수에 대입하세요. View Composer로 지어줬던 이름을 정확히 문자열로 제공해야 한다는 점을 유의하세요. 작성하신 createComponents 매쏘드를 답으로 제출해 주세요.


createComponents
super createComponents.

items := self add:  ListPresenter new name: 'book list'.


Workspace에서 HouseKeepingBookShell showOn: testBook 해서 다시 창을 열어봅니다. 리스트가 추가 되었나요? 캡쳐해서 답으로 제출하세요.


/



4. 그런데 리스트박스가 비어있군요. 내용을 표시해야 합니다.
HouseKeepingBookShell에 model: 이라는 매쏘드를 추가합니다. 이것도 역시 3번 문제와 마찬가지로 model:의 정의를 참고합니다. model: 매쏘드는 이 GUI객체(Shell)에 모델을 넘길 때, 그것을 받아들이는 매쏘드입니다. 문제 3번에서 추가한 리스트는 Shell의 하위창이었죠? 이 하위창도 역시 MVP구조로 되어있기 때문에 모델을 공급해줘야 제대로 동작합니다. 무엇을 넘겨주면 좋을까요?

items model: ????????????????


HouseKeepingBookShell>>model: 매쏘드를 작성한 것을 답으로 제출하세요.


model: aHouseKeepingBook
items model: aHouseKeepingBook items.


Workspace에서 HouseKeepingBookShell showOn: testBook 를 캡쳐해서 답으로 제출하세요.




5. 이제 하위 창을 하나 더 추가 하겠습니다. 방법은 2번~4번에서 했던 것과 마찬가지로 진행하시면됩니다. 객체변수 pocketMoney를 만듭니다. Class Composer의 클래스트리에서 팝업메뉴 View/Edit···· 해서 View Composer를 엽니다. 뷰툴박스에서 NumberPresenter.Default View를 추가하고 이름을 pocket money로 짓고 저장한다음, HouseKeepingBookShell에서 createComponents매쏘드와 model:매쏘드를 수정해서 새 객체변수 pocketMoney도 items처럼 수정해줍니다.


수정된 createComponents매쏘드와 model:매쏘드를 답으로 제출하세요.


pocketMoney := self add: TextPresenter new name: 'pocket money'.


pocketMoney model: aHouseKeepingBook pocketMoney.



Workspace에서 HouseKeepingBookShell showOn: testBook 를 하여 원금과 가계부 항목이 잘 표시된 모습을 캡쳐해서 답으로 제출하세요.





6. 리스트에 아마 an HouseKeepingBookItem이라고만 표시되고 있을 겁니다. 그것은 리스트에게 받은 객체들을 어떤 형태로 표현할 지 말해주지 않았기 때문에 기본적으로 표시되는 문자열만 뵤여주고 있기 때문입니다. 다시 View Composer를 열어서 book list라는 리스트를 선택하면 오른쪽에서 속성으로 getTextBlock이라고 있습니다. selector에 #displayString이라고 되어 있을 겁니다. 그걸 #stringInTheListBox'라고 고쳐주고 저장한다음 View Composer를 닫습니다. 그런 다음 다시 showOn:해서 창을 열어봅니다. 에러가 날 겁니다. 디버거로 매쏘드를 추가하는 방법 기억하시죠? 그 방법으로 HouseKeepingBookItem에 매쏘드를 만들어줍니다. 방금 만든 그 매쏘드는 리스트가 자신의 아이템들인 HouseKeepingBook객체들에게 표시할 문자열을 요구하는 매쏘드입니다. HouseKeepingBookItem의 name과 value를 문자열로 답하는 매쏘드를 작성해보세요.(숙제하는 사람 마음대로) 다시 showOn:합니다.


HouseKeepingBookItems>>stringInTheListBox 매쏘드를 답으로 제출하세요.


stringInTheListBox
^self name,' : ',self value printString


showOn: 하여 리스트에 항목들이 제대로 표시된 모습을 캡처해서 제출하세요.





7. 합산을 표시하는 작은 창도 만들어 보겠습니다. View Composer를 열어 NumberPresenter.Default View를 추가하여 sum이라고 이름 짓습니다.
HouseKeepingBookShell에 sum이라는 객체변수를 만들고 createComponents와 model: 매쏘드를 다시 수정합니다. 모델인 HouseKeepingBook객체에게 sum을 물어서 그 것을 HouseKeepingBookShell의 sum에게 모델로 넘겨주면 되겠군요.


createComponents, model: 를 답으로 제출하세요.


sum := self add: NumberPresenter new name: 'sum'.

sum model: aHouseKeepingBook sum.


합산이 잘 표시된 창을 캡처해서 답으로 제출하세요.




8. 흑자와 적자를 표시하는 창도 만들어 보겠습니다. View Composer를 열어 TextPresenter.Stati text를 추가하여 status이라고 이름 짓습니다.
HouseKeepingBookShell에 status이라는 객체변수를 만들고 createComponents와 model: 매쏘드를 다시 수정합니다. 모델인 HouseKeepingBook객체에게 흑자인지 적자인지 문자열로 답해주는(그런 매쏘드가 있었지요?) 그것을 HouseKeepingBookShell의 status에게 모델로 넘겨주면 되겠군요.


createComponents, model: 를 답으로 제출하세요.


status := self add: TextPresenter new name: 'status'.

status model: aHouseKeepingBook statusString.



흑자/적자가 잘 표시된 창을 캡처해서 답으로 제출하세요.



posted by 초딩입맛제주아재
2006. 10. 11. 09:31 삶은달걀

네이버 접속했더니 뜨는 이야기에 이게 떴길래 봤다.
키보드를 새로 장만하고 싶은 마음이 몇달째인가....
http://www.phantom.net/content/products/index.html
팬텀이라니...갑자기 전에 키우던 리니지2 충성이 캐릭이 생각난다...
2차 서브가 팬텀이었는데...그 막강한 화력과 카리스마 넘치는 뽀대...
아...팔고 나니 무지 후회되는구나...
애니튼..
키캡을 보아하니 팬타그래프 같기도 하고 아닌것 같기도 하고...
팬타그래프면 좋으련만...
마우스도 그럭저럭 봐줄만 하긴 한데 네비게이션 버튼이 없는것 같다..
무엇보다 10미터나 보장되는 무선거리가 맘에 드는데...
가격이 $129.95....뭐이리 비싸 -_-
posted by 초딩입맛제주아재
2006. 10. 10. 11:35 삶은달걀
http://interfacelift.com/



이쁜 바탕화면과 깔끔한 아이콘, 테마가 가득한 사이트.
인터페이스도 깔끔하고
와이드용 바탕화면도 제공한다.
특히 아이콘의 경우 Mac스타일의 세련된 아이콘이 많다.
적극 추천!!!
posted by 초딩입맛제주아재
2006. 10. 9. 11:08 Programing/HTML/JavaScript/CSS
if(object.addEventListener) {
   object.addEventListener('change',event_listener,false);
}else{
   object.attachEvent('onchange',event_listener);
}

function event_listener(){
   alert('object 의 change 이벤트에 반응하는 리스너');
}

- 이벤트 리스너 추가 메서드
   IE        : attachEvent(event.type,listener)
   Mozila : addEventListener(event.type,listener,useCapture)
   * Mozila 의 event.type 은 IE의 그것과는 달리 접두사 'on'이 붙지 않는다는점에 유의.


- 이벤트 리스너 삭제 메서드
   IE        : object.detachEvent(event.type,listener)
  Mozila : removeEventListener(event.type,listener,useCapture)

posted by 초딩입맛제주아재
2006. 10. 9. 10:15 Programing/Smalltalk

payroll := OrderedCollection new.

attendanceDate := Date fromString: '2006-10-1'.
attendanceTime := Time fromString: '10:00'.
attendanceDateTime := TimeStamp date: attendanceDate time: attendanceTime.

finishDate := Date fromString: '2006-10-1'.
finishTime := Time fromString: '19:00'.
finishDateTime := TimeStamp date: finishDate time: finishTime.


날짜와 시간으로 출근시간과 퇴근시간에 해당하는 timestamp 를 만들어서
patroll 에 한쌍으로 묶어서 넣으려고 하는데 들어가질 않습니다.

자동완성이 되지 않아 직접 타이핑으로
payroll add: #(attendanceDateTime finishDateTime).
입력을 했더니 입력은 됐으나 이상한 형태로 되었더군요.

#(#attendanceDateTime #finishDateTime)

어떠한 형태의 객체도 다 포함하는 줄 알았던 컬렉션 객체가 말썽을 부리니
멍해지네요 -_-;;

달룟님의 답변

지적하신 부분은 "어떠한 객체도 다 담을 수 있다."와는 상관이 없습니다. Smalltalk문법에서 #(변수명, 변수명) 는 허용되지 않는 표현입니다. #(표현식, 표현식) 역시 마찬가지입니다. #()속에는 literal만 올 수 있습니다. 이 부분은 Ruby에 비해서 불편한 점으로, Smalltalker들 중에는 이 문법을 고치자는 주장도 나오고 있습니다.
파란글씨로 표시된 것처럼, Symbol객체 2개로 된 배열로 인식됩니다. 컴파일된 소스색깔을 보시면 변수명이 아니라 literal로서 컴파일 되었음을 알 수 있습니다.

원하시는 표현은 Array with: attendanceDateTime with: finishDateTime 입니다.


#()는 Array객체를 간략한 표현으로 생성하는 문법입니다. #()로 OrderedCollection객체를 만들 수는 없습니다. 변환은 가능하죠.

#(1 2 3) asOrderedCollection.

혹은

OrderedCollection withAll: #(1 2 3).

with:with:는 Collection 클래스에 있는 매쏘드이기 때문에 Array, OrderedCollection모두 쓸 수 있습니다.

OrderedCollection with: attendanceDateTime with: finishDateTime.

이라고 하면 되죠.



이렇게 하니 된다.

payroll add: (Array with: attendanceDateTime with: finishDateTime).
payroll size. > 1
(payroll at: 1) size. > 2


Collection >> OrderedCollection,Array,SortedCollection...

'Programing > Smalltalk' 카테고리의 다른 글

사용자의 실수를 막아주는 queryCommand:  (0) 2006.10.28
가계부 만들기 - 05  (0) 2006.10.11
가계부 만들기 - 04  (0) 2006.10.08
가계부 만들기 - 03  (0) 2006.10.08
가계부 만들기 - 02  (0) 2006.10.08
posted by 초딩입맛제주아재
2006. 10. 8. 15:21 Programing/Smalltalk
- GUI 만들기 -


1.
Shell 클래스 아래 HouseKeepingBookShell 클래스를 만듭니다.(이것은 MVP에서 P인 Presenter에 해당합니다)

Workspace에서 HouseKeepingBookShell showOn: testBook 을 실행해 봅니다.


창이 새로 열리죠? 그것을 캡쳐해서 올려주세요.






2. Class Browser의 클래스트리에서 HouseKeepingBookShell 의 팝업메뉴 View... / New를 합니다. (이것은 MVP에서 V인 View에 해당합니다) 이름은 그냥 기본으로 있는 Default View로 엔터누릅니다. View Composer가 열렸죠. 1번 문제에서 봤던 창이 있을 겁니다. 이 창을 편집한다는 소리죠. View Composer로 왼쪽에 뷰툴박스를 열어서 ListPresenter.Default View를 찾아 이 창에다 추가해줍니다.(끌어다놓기하면 됩니다) 오른쪽 하단의 속성창에서 name이라는 항목을 찾아 문자열로 book list 라고 이름 지어줍니다. View Composer를 저장하고 닫습니다.


Workspace에서 HouseKeepingBookShell showOn: testBook 을 실행해 봅니다.


창이 새로 열리죠? 그것을 캡쳐해서 올려주세요.




3. HouseKeepingBookShell 에 items라는 객체변수를 만듭니다. createComponents라는 매쏘드를 검색(Definitions of...)해 봅니다. 그 매쏘드들을 보고 흉내내서 ListPresenter를 만들어 items변수에 대입하세요. View Composer로 지어줬던 이름을 정확히 문자열로 제공해야 한다는 점을 유의하세요. 작성하신 createComponents 매쏘드를 답으로 제출해 주세요.


createComponents
super createComponents.

items := self add:  ListPresenter new name: 'book list'.


Workspace에서 HouseKeepingBookShell showOn: testBook 해서 다시 창을 열어봅니다. 리스트가 추가 되었나요? 캡쳐해서 답으로 제출하세요.




4. 그런데 리스트박스가 비어있군요. 내용을 표시해야 합니다.
HouseKeepingBookShell에 model: 이라는 매쏘드를 추가합니다. 이것도 역시 3번 문제와 마찬가지로 model:의 정의를 참고합니다. model: 매쏘드는 이 GUI객체(Shell)에 모델을 넘길 때, 그것을 받아들이는 매쏘드입니다. 문제 3번에서 추가한 리스트는 Shell의 하위창이었죠? 이 하위창도 역시 MVP구조로 되어있기 때문에 모델을 공급해줘야 제대로 동작합니다. 무엇을 넘겨주면 좋을까요?

items model: ????????????????


HouseKeepingBookShell>>model: 매쏘드를 작성한 것을 답으로 제출하세요.


model: aHouseKeepingBook
items model: aHouseKeepingBook items.


Workspace에서 HouseKeepingBookShell showOn: testBook 를 캡쳐해서 답으로 제출하세요.





5. 이제 하위 창을 하나 더 추가 하겠습니다. 방법은 2번~4번에서 했던 것과 마찬가지로 진행하시면됩니다. 객체변수 pocketMoney를 만듭니다. Class Composer의 클래스트리에서 팝업메뉴 View/Edit···· 해서 View Composer를 엽니다. 뷰툴박스에서 NumberPresenter.Default View를 추가하고 이름을 pocket money로 짓고 저장한다음, HouseKeepingBookShell에서 createComponents매쏘드와 model:매쏘드를 수정해서 새 객체변수 pocketMoney도 items처럼 수정해줍니다.


수정된 createComponents매쏘드와 model:매쏘드를 답으로 제출하세요.


pocketMoney := self add: TextPresenter new name: 'pocket money'.


pocketMoney model: aHouseKeepingBook pocketMoney.



Workspace에서 HouseKeepingBookShell showOn: testBook 를 하여 원금과 가계부 항목이 잘 표시된 모습을 캡쳐해서 답으로 제출하세요.





6. 리스트에 아마 an HouseKeepingBookItem이라고만 표시되고 있을 겁니다. 그것은 리스트에게 받은 객체들을 어떤 형태로 표현할 지 말해주지 않았기 때문에 기본적으로 표시되는 문자열만 뵤여주고 있기 때문입니다. 다시 View Composer를 열어서 book list라는 리스트를 선택하면 오른쪽에서 속성으로 getTextBlock이라고 있습니다. selector에 #displayString이라고 되어 있을 겁니다. 그걸 #stringInTheListBox'라고 고쳐주고 저장한다음 View Composer를 닫습니다. 그런 다음 다시 showOn:해서 창을 열어봅니다. 에러가 날 겁니다. 디버거로 매쏘드를 추가하는 방법 기억하시죠? 그 방법으로 HouseKeepingBookItem에 매쏘드를 만들어줍니다. 방금 만든 그 매쏘드는 리스트가 자신의 아이템들인 HouseKeepingBook객체들에게 표시할 문자열을 요구하는 매쏘드입니다. HouseKeepingBookItem의 name과 value를 문자열로 답하는 매쏘드를 작성해보세요.(숙제하는 사람 마음대로) 다시 showOn:합니다.


HouseKeepingBookItems>>stringInTheListBox 매쏘드를 답으로 제출하세요.


stringInTheListBox
^self name,' : ',self value printString


showOn: 하여 리스트에 항목들이 제대로 표시된 모습을 캡처해서 제출하세요.





7. 합산을 표시하는 작은 창도 만들어 보겠습니다. View Composer를 열어 NumberPresenter.Default View를 추가하여 sum이라고 이름 짓습니다.
HouseKeepingBookShell에 sum이라는 객체변수를 만들고 createComponents와 model: 매쏘드를 다시 수정합니다. 모델인 HouseKeepingBook객체에게 sum을 물어서 그 것을 HouseKeepingBookShell의 sum에게 모델로 넘겨주면 되겠군요.


createComponents, model: 를 답으로 제출하세요.


sum := self add: NumberPresenter new name: 'sum'.

sum model: aHouseKeepingBook sum.



합산이 잘 표시된 창을 캡처해서 답으로 제출하세요.




8. 흑자와 적자를 표시하는 창도 만들어 보겠습니다. View Composer를 열어 TextPresenter.Stati text를 추가하여 status이라고 이름 짓습니다.
HouseKeepingBookShell에 status이라는 객체변수를 만들고 createComponents와 model: 매쏘드를 다시 수정합니다. 모델인 HouseKeepingBook객체에게 흑자인지 적자인지 문자열로 답해주는(그런 매쏘드가 있었지요?) 그것을 HouseKeepingBookShell의 status에게 모델로 넘겨주면 되겠군요.


createComponents, model: 를 답으로 제출하세요.


status := self add: TextPresenter new name: 'status'.

status model: aHouseKeepingBook statusString.



흑자/적자가 잘 표시된 창을 캡처해서 답으로 제출하세요.




'Programing > Smalltalk' 카테고리의 다른 글

가계부 만들기 - 05  (0) 2006.10.11
변수 이름으로 배열 만들기 - Array with: 변수명 with: 변수명  (0) 2006.10.09
가계부 만들기 - 03  (0) 2006.10.08
가계부 만들기 - 02  (0) 2006.10.08
가계부 만들기 - 01  (0) 2006.10.08
posted by 초딩입맛제주아재
2006. 10. 8. 15:16 Programing/Smalltalk

1. Class Browser로 Object의 하위 클래스로 HouseKeepingBookItem 클래스를 만드세요.
    객체변수는 name value date 3개입니다.
    아무런 매쏘드도 없는 빈 껍데기 클래스입니다.

Object subclass: #HouseKeepingBookItem
instanceVariableNames: 'name value date'
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''


2. 다음을 실행하세요

testItem := HouseKeepingBookItem new.
testItem name: '스포츠신문'.

에러가 납니까? 당연합니다! HouseKeepingBookItem에 name: 이라는 매쏘드를 안만들어 줬으니까요. "Debug"버튼을 누릅니다. 디버깅 창의 왼쪽 상단 리스트에 팝업메뉴를 불러 "implement·······"메뉴를 고릅니다. 어떤 클래스에다 만들지 물어보네요. 답해줍니다.
임시 매쏘드가 만들어졌을 겁니다. 객체변수 name에 인자를 저장하는 매쏘드로 바꿔주고 accept(Ctrl+S)해줍니다.

testItem name: '스포츠신문'.를 다시 한번 해봅니다. 에러가 납니까?

name: aString

name := aString.


3.
다음의 문장들도 하나씩 실행하고 2번과 같이 매쏘드를 만들어줍니다.

testItem value: 500.
testItem date: Date today.
testItem name.
testItem value.
testItem date.

name
^name

value: anInteger
value := anInteger.

value
^value

date: aDate
date := aDate.

date
^date


4.
기존에 Workspace에 housekeepingbook에 저장되어있던 항목들(OrderedCollection type)을 전부 HouseKeepingBookItem 객체로 대체합니다.

housekeepingbook := housekeepingbook collect: [:item| ?????????? ].
??????????에 들어갈 적당한 표현식을 찾으세요.

housekeepingbook := housekeepingbookcollect: [ :each |
         HouseKeepingBookItem  new
                name: (each at: 1);
                value: (each at: 2);
                date: (each at: 3)
].


5.
숙제 1과 2의 문제들을 다 다시 작성해보세요.^^(놀라지 마시고 살짝씩만 바꿔주면 됩니다.) 기존에 OrderedCollection을 쓸 때와 비교했을 때 어떤 점이 달라졌는지 느낌 점을 말씀해주세요.

원하는 값에 바로 접근이 가능해진것 같아요...
마치 연관배열처럼 키값에 의한 access 같은...좀더 편해졌다고 할까요..


6. Class Browser로 Object의 하위 클래스로 HouseKeepingBook 클래스를 만드세요.
    객체변수는 pocketMoney items 2개 입니다.
    아무런 매쏘드도 없는 빈 껍데기 클래스입니다.

Workspace에 있는 변수들 pocketMoney와 housekeepingbook을 각각 testBook의 pocketMoney와 items에 담습니다. 2번과 같은 방법으로 하시면 됩니다.

Object subclass: #HouseKeepingBook
instanceVariableNames: 'pocketMoney items'
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''

items: aItem
items := aItem.

items
^items.

pocketMoney: aInteger
pocketMoney := aInteger.

pocketMoney
^pocketMoney.


7. HouseKeepingBook 에 sum 이라는 매쏘드를 만들어서 금액의 총합을 리턴하게 하세요. (원금을 포함하도록 하세요)

sum

^self items inject: pocketMoney into: [
:sum :item |
sum + (item value)
]


8. HouseKeepingBook 에 본인이 흑자인지 물어보는 isSurplus라는 매쏘드를 만드세요. true/false를 리턴해야 합니다. 7번 문제의 sum 매쏘드를 사용해야 합니다.

isSurplus

^(self sum > 0)


9. HouseKeepingBook 에 statusString라는 매쏘드를 만들어, 흑자면, '아싸! 흑자' 적자면 '에고... 적자'라는 문자열을 답하게 하세요. 8번 문제의 isSurplus를 사용해야 합니다.

statusString

self isSurplus ifTrue: [^'아싸!흑자'] ifFalse: [^'에고...적자']


10.
HouseKeepingBook 에 itemsOfYear: 라는 매쏘드를 만들어, 그 해의 항목들을 답하도록 하세요. 숙제 2의 답을 활용하세요.

itemsOfYear: aYear

^self items select: [:each | each date year = aYear]



11. HouseKeepingBook 에 sumOfYear: 라는 매쏘드를 만들어, 그 해 항목들의 합을 답하도록 하세요. itemsOfYear: 매쏘드를 활용하세요. (원금은 포함하지 않습니다)

sumOfYear: aYear

^(self itemsOfYear: aYear) inject: 0 into: [:sum :item | sum + (item value)]

posted by 초딩입맛제주아재
2006. 10. 8. 15:13 Programing/Smalltalk

WorkSpace 에서 끄적거리기 두번째....

select: 의 활용

housekeepingbook := OrderedCollection  new.

housekeepingbook
add: #('복권' -5000 '2005-09-21') asOrderedCollection;
add: #('복권당첨' 50000 '2006-09-21') asOrderedCollection;
add: #('두부' -500 '2006-09-22') asOrderedCollection;
add: #('피자' -15000 '2006-09-23') asOrderedCollection;
add: #('보너스' 100000 '2004-09-24') asOrderedCollection;
add: #('화장지' -7000 '2006-09-24') asOrderedCollection;
add: #('전기세' -25000 '2006-09-24') asOrderedCollection;
add: #('키보드' -15000 '2005-09-25') asOrderedCollection;
add: #('화장품' -55000 '2006-09-25') asOrderedCollection;
add: #('전구' -500 '2004-09-26') asOrderedCollection.

"1.housekeepingbook의 3번째 원소를 Date객체로 바꾸기"
housekeepingbook do: [:each | each at: 3 put: (Date fromString: (each at: 3))].

"2.2004년 항목만 추출"
housekeepingbook select: [:each | (each at: 3) year = 2004].

"3.2004년의 금액 합계"
(housekeepingbook select: [:each | (each at: 3) year = 2004]) inject: 0 into: [:sum :item|  sum + (item at: 2) ].

"4.각 항목들의 요일"
housekeepingbook collect: [:each | (each at: 3) weekday].


"5.category 객체 생성 & 전기세의 항목 이름"
categories := OrderedCollection new.
categories
add: #('두부' '피자' '김치') -> '식료품';
add: #('복권' '복권당첨' '적금') -> '투자';
add: #('월급' '보너스') -> '급여';
add: #('전기세' '수도세') -> '생활요금';
add: #('화장지' '키보드' '화장품' '전구') -> '소모품'.

(categories detect: [:each | each key includes: '전기세']) value.

"6.각 항목의 분류"
housekeepingbook collect: [:item | (categories detect: [:each | each key includes: (item at: 1) ]) value].

"7.소모품으로 분류되는 항목의 합"
(housekeepingbook select: [:each | (categories detect: [:cat | cat value = '소모품']) key includes: (each at: 1) ])
inject: 0 into: [:sum :item | sum + (item at: 2)].

"8.2006년의 소모품의 합"
((housekeepingbook select: [:each | (categories detect: [:cat | cat value = '소모품']) key includes: (each at: 1) ])
select: [:each | (each at: 3) year = 2006]) inject: 0 into: [:sum :item | sum + (item at: 2) ].

"9.원금"
pocketMoney := 4000000.
housekeepingbook inject: pocketMoney into: [:sum :item | sum + (item at: 2) ].

'Programing > Smalltalk' 카테고리의 다른 글

가계부 만들기 - 04  (0) 2006.10.08
가계부 만들기 - 03  (0) 2006.10.08
가계부 만들기 - 01  (0) 2006.10.08
변수와 메세지 그리고 이벤트...  (0) 2006.05.15
재밌다...  (0) 2006.05.07
posted by 초딩입맛제주아재
2006. 10. 8. 15:07 Programing/Smalltalk

WorkSpace 에서 끄적거리기....



"1.OrderCollection 객체생성"
housekeepingbook := OrderedCollection  new.


"2~3.항목추가"
housekeepingbook add: #('복권' -5000 '2006-09-21');
add: #('복권당첨' 50000 '2006-09-21');
add: #('두부' -500 '2006-09-22');
add: #('피자' -15000 '2006-09-23');
add: #('보너스' 100000 '2006-09-24');
add: #('화장지' -7000 '2006-09-24');
add: #('전기세' -25000 '2006-09-24');
add: #('키보드' -15000 '2006-09-25');
add: #('화장품' -55000 '2006-09-25');
add: #('전구' -500 '2006-09-26').


"4.항목 갯수"
housekeepingbook size.


"5.첫번째 항목"
housekeepingbook at: 1.


"6.첫번째 항목의 금액"
(housekeepingbook at: 1) at: 2.


"7.전체 항목의 금액"
housekeepingbook collect: [:each| each at: 2 ]


"8.전체 금액의 합"
(housekeepingbook collect: [:each| each at: 2 ]) inject: 0 into: [:sum :each| each + sum ]


"9.항목의 평균 금액"
avg := ((housekeepingbook collect: [:each| each at: 2 ]) inject: 0 into: [:sum :each| each + sum ]) / housekeepingbook size


"10.흑자 또는 적자"
(avg > 0) ifTrue: ['흑자'] ifFalse: ['적자'].

'Programing > Smalltalk' 카테고리의 다른 글

가계부 만들기 - 04  (0) 2006.10.08
가계부 만들기 - 03  (0) 2006.10.08
가계부 만들기 - 02  (0) 2006.10.08
변수와 메세지 그리고 이벤트...  (0) 2006.05.15
재밌다...  (0) 2006.05.07
posted by 초딩입맛제주아재