2016년 7월 22일 금요일

카카오api 나에게 보내기 (REST API) classic asp

카카오api 주소 (https://developers.kakao.com/)

예제 소스는 classic asp로 구현했습니다.

나에게 보내기Copy URL

카카오톡 나에게 보내기는 사용자 중에서 카카오계정에 연결한 카카오톡 사용자에 한해 카카오톡 나와의 챗팅방으로 메시지를 보낼 수 있는 기능입니다. 해당 기능을 사용하기 위해서는 성공적인 로그인 후에 얻을 수 있는 사용자 토큰이 필요합니다.
(https://developers.kakao.com/docs/restapi#카카오톡-나에게-보내기)


1. 카카오 개발자 등록
https://accounts.kakao.com/login?continue=https://developers.kakao.com/login



2. 내 애플리케이션 추가작업



3. 사용자관리 설정


일반을 클릭하면 rest api 키를 얻을수 있습니다. 밑에 소스에서 client_id 변수에 이 값을 넣어주셔야됩니다.


4. 템플릿 추가


5. restapi key 확인 및 도메인 등록
내어플리케이션 >  설정 > 일반 > REST API 키 확인, 사이트 도메인 등록, path 등록




6. 로그인 처리
https://developers.kakao.com/docs/restapi#사용자-관리-로그인

ex>
https://kauth.kakao.com/oauth/authorize?client_id={client_id}&redirect_uri={등록한 path}&response_type=code


7. 토큰받기 처리 및 나에게 메시지 전송
등록한 path 페이지에서 code라는 request 값을 받는다.
받은 code값을 이용하여 token 값을 요청




[aaa.asp 페이지]



'async 함수
Function postFormData(url, headerArr, data) Dim xhr, i Set xhr = Server.CreateObject("MSXML2.ServerXMLHTTP.3.0") xhr.open "POST", url, false for i = 0 to ubound(headerArr) xhr.setRequestHeader headerArr(i)(0), headerArr(i)(1) next xhr.send data If (xhr.Status = 200) then postFormData = xhr.ResponseText response.write postFormData Else Err.Raise 1001, "postFormData", "Post to " & url & " failed with " & xhr.Status&" message "&xhr.responseText End If End Function


 client_id = "38c9*********************8" 
 url = "https://주소.co.kr/index22.asp"
        code = request("code")

  '토큰 요청 값 받기 
  '최초 요청을 보냈을시 access_token, refresh_token
  set tokenObj = JSON.parse(
                  postFormData("https://kauth.kakao.com/oauth/token", 
                  array(array("Content-Type","application/x-www-form-urlencoded")),
                  "grant_type=authorization_code&client_id="&client_id&"&redirect_uri="&url&"&code="&code))
  
  access_token = tokenObj.access_token  
  refresh_token = tokenObj.refresh_token

  'refresh token 요청 값 받기  
  'refresh_token은 기본 12시간~24시간이 아닌 더 긴 시간을 유지할수 있는 token임 
  set refreshTokenObj = JSON.parse(
                        postFormData("https://kauth.kakao.com/oauth/token",
                        array(array("Content-Type","application/x-www-form-urlencoded")),
                        "grant_type=refresh_token&client_id="&client_id&"&redirect_uri="&url&"&refresh_token="&refresh_token))

  'refresh token 요청시 access_token만 넘어옴 
  access_token = refreshTokenObj.access_token

  'access_token 값을 이용하여 message 보내기
  response.write postFormData("https://kapi.kakao.com/v1/api/talk/memo/send?template_id=828&args="&
                 Server.URLEncode("{""${message}"":""테스트적용완료"",""${subject}"":""적용완료""}"),
                 array(array("Authorization", "Bearer "& access_token)),"")





위와 같이 나에게 메시지가 옴 


- 나에게 보낸다는 서비스이기때문에 광범위하게 사용하기에 제약사항이 좀 있습니다. 
구현하시서 생각해보시길..

2016년 6월 20일 월요일

flyweight 패턴

■ 정의

[GOF]
 - 공유를 통한 많은 수의 소립 객체들을 효과적으로 지원

[ 실용주의 디자인패턴 ]
- 메모리 사용량을 줄이기 위해 외부 상태(상태정보 저장, 계산)를 사용하거나
  공유(객체의 복사본 대신 단일 객체에 대한 다중 참조를 이용)한다.
- 무엇을 하느냐에 의해 정의, 즉 메소드에 의해 정의됨

▶ 즉 공유하는 객체를 이용하되 상태 정보를 외부 객체가 따로 관리



■ 사용 예
- game of life를 단순하게 구현할때 '셀'이 살아있는가?는 주변 상태를 참조를 지니고 있어야된다. 1024*1024를 표현하려해도 40mb가 필요함
flywieght를 사용하면 동일한 상태를 지닌 객체가 단 하나의 객체를 통해 표현



■ 장/단점
- 장점 : flyweight를 사용하지 않으면 객체지향적으로 구현하기가 힘듬
- 장점 : flyweight 풀을 이용하면 자바의 == 연산자로 객체의동일성 여부를 결정 할 수 있다.

- 단점 : 외부상태가 계산되는 값이라면(매번 데이터베이스에 접근) 하면 접근이 느릴 수 있다.
- 단점 : 코드가 복잡해짐, 유지보수를 어렵게하고 코드가 커질 수 있음


■ 코드 예제
쉬운 예>
ElementStyle e = new ElementStyle;
e.setMargin(ElementStyleFactory.createMargin(10,10,20,10)); -> 객체는 공유하되 외부 객체가 따로 관리 되도록

게임프로그래밍 패턴예제(js로 구현)>
[origin]
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flyweight origin</title>
</head>
<body>
경량패턴??<br>
어떤 객체의 수가 너무 많아 좀 가볍게 만들고 싶을때 사용<br>
고유상태와 외부상태로 나눔<br>
<br>
예제 : 지형 만들기<br>
타일(고유상태)과 각 타일들이 갖고 있는 정보(외부상태)<br>
<script>
    function Terrain(kind){
        return {
            "TERRAIN_CLASS" : "TERRAIN_CLASS",
            "TERRAIN_HILL" : "TERRAIN_HILL",
            "TERRAIN_RIVER" : "TERRAIN_RIVER"        }[kind];
    }

    function World(){
        this.tiles = {};
    }
    World.prototype.getMovementCost = function(x,y){
        return {
            "TERRAIN_CLASS" : 1,
            "TERRAIN_HILL" : 2,
            "TERRAIN_RIVER" : 3        }[this.tiles[x][y]];
    };

    World.prototype.getIsWater = function(x,y){
        return {
            "TERRAIN_CLASS" : false,
            "TERRAIN_HILL" : false,
            "TERRAIN_RIVER" : true        }[this.tiles[x][y]];
    };

    World.prototype.setTile = function(x,y, value){
        this.tiles = this.tiles||{};

        this.tiles[x] = this.tiles[x]||{};
        this.tiles[x][y] = this.tiles[x][y]||"";
        this.tiles[x][y] = value;

    };


    function Main(){
        var world = new World;
        var terrain_class = Terrain("TERRAIN_CLASS");
        var terrain_hill = Terrain("TERRAIN_HILL");
        var terrain_river = Terrain("TERRAIN_RIVER");

        world.setTile(1,1,terrain_class) ;
        world.setTile(1,2,terrain_hill) ;
        world.setTile(1,3,terrain_river) ;

        console.log(world.getIsWater(1,3));
        console.log(world.getMovementCost(1,2));
    }

    window.onload = function(){
        Main();
    }
</script>
</body>
</html>

[fly weight]
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flyweight </title>
</head>
<body>
경량패턴??<br>
어떤 객체의 수가 너무 많아 좀 가볍게 만들고 싶을때 사용<br>
고유상태와 외부상태로 나눔<br>
<br>
예제 : 지형 만들기<br>
타일(고유상태)과 각 타일들이 갖고 있는 정보(외부상태)<br>
<script>
    function Terrain(movementCost, isWater, texture){

        var movementCost_;
        var isWater_;
        var texture_;

        function _Terrain(){
            this.movementCost_ = movementCost;
            this.isWater_ = isWater;
            this.texture_ = texture;

        }

        _Terrain.prototype.getMovementCost = function(){
            return this.movementCost_;
        };
        _Terrain.prototype.isWater = function(){
            return this.isWater_;
        };
        _Terrain.prototype.getTexture = function(){
            return this.texture_;
        };


        if(!(this instanceof _Terrain )){
            return new _Terrain();
        }

    }

    var CONST_GLASS_TEXTURE = "GLASS_TEXTURE";
    var CONST_HILL_TEXTURE = "HILL_TEXTURE";
    var CONST_RIVER_TEXTURE = "RIVER_TEXTURE";
    var CONST_WIDTH = 10;
    var CONST_HEIGHT = 12;

    function World(){

        var tiles = {};


        function _World(){
            this.glassTerrain_ = [1,false,CONST_GLASS_TEXTURE];
            this.hillTerrain_ = [2,false,CONST_HILL_TEXTURE];
            this.riverTerrain_ = [3,true,CONST_RIVER_TEXTURE];
            this.tiles = tiles;

        }

        _World.prototype.setTile = function(x,y, value){
            this.tiles = this.tiles||{};

            this.tiles[x] = this.tiles[x]||{};
            this.tiles[x][y] = this.tiles[x][y]||"";
            this.tiles[x][y] = value;

        };

        _World.prototype.getTile = function(x,y){

            return Terrain.apply(this, this.tiles[x][y]);
        };


        _World.prototype.generateTerrain = function(){
            for(var x=0; x < CONST_WIDTH; x++) {
                for(var y=0; y < CONST_HEIGHT; y++){
                    if(x % 2 == 0){
                        this.setTile.apply(this, [x,y,this.glassTerrain_]);
                    }else{
                        this.setTile.apply(this, [x,y,this.hillTerrain_]);
                    }
                    if(y % 3 == 1){
                        this.setTile.apply(this, [x,y,this.riverTerrain_]);
                    }
                }
            }
        };

        if(!(this instanceof _World )){
            return new _World();
        }

    }



    function Main(){
        var world = World();
        world.generateTerrain();
        console.dir(world.getTile(1,1).getMovementCost());

    }

    window.onload = function(){
        Main();
    }
</script>
</body>
</html>

2016년 6월 19일 일요일

게임프로그래밍 패턴 - 커맨드패턴을 이용한 이동키로 화면 움직이기 구현

아래는 원본 함수
handleInput에 if문으로 각각의 함수를 호출 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>command pattern</title>
    <style>
        #unit {
            position: absolute;
            background-color: olivedrab;
            top:100px;
            left:100px;
            display:block        }
    </style>
</head>
<body>
원본소스
<div id="unit">
    unit
</div>
<script>
    document.addEventListener("keydown", handleInput, false);
    function handleInput(e){
        var keyCode = e.keyCode;
        if(keyCode == 38){
            up();
        }else if(keyCode == 40){
            down();
        }else if(keyCode == 37){
            left();
        }else if(keyCode == 39){
            right();
        }
    };


    function unit(){
        var target = document.getElementById('unit');

        return {
            "x" : parseInt(getStyle(target,"left"),10),
            "y" : parseInt(getStyle(target,"top"),10),
            "body" : target.style        };
    }
window.onload= function(){
    console.log(unit().x);
};


</script>

<script>


    function getStyle(el, styleProp) {
        var value, defaultView = (el.ownerDocument || document).defaultView;
        // W3C standard way:        if (defaultView && defaultView.getComputedStyle) {
            // sanitize property name to css notation            // (hypen separated words eg. font-Size)            styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
            return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
        } else if (el.currentStyle) { // IE            // sanitize property name to camelCase            styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
                return letter.toUpperCase();
            });
            value = el.currentStyle[styleProp];
            // convert other units to pixels on IE            if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
                return (function(value) {
                    var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
                    el.runtimeStyle.left = el.currentStyle.left;
                    el.style.left = value || 0;
                    value = el.style.pixelLeft + "px";
                    el.style.left = oldLeft;
                    el.runtimeStyle.left = oldRsLeft;
                    return value;
                })(value);
            }
            return value;
        }
    }

function up(){
    var target = unit().y;
    return unit().body.top = suffixValue(target, -3);
}

    function down(){
        var target = unit().y;
        return unit().body.top = suffixValue(target, +3);
    }

    function left(){
        var target = unit().x;
        return unit().body.left = suffixValue(target, -3);
    }

    function right(){
        var target = unit().x;
        return unit().body.left = suffixValue(target, +3);
    }

function suffixValue(target, value){
    var suffix = "px";
    return (target + value)+suffix;
}

</script>
</body>
</html>


커맨드 패턴을 이용하여 각각의 메서드 호출을 실체화 함, and undo, redo 구현

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>command pattern</title>
    <style>
        #unit {
            position: absolute;
            background-color: olivedrab;
            top:100px;
            left:100px;
            display:block        }
    </style>
</head>
<body>
메서드의 호출을 실체화 함
<div id="unit">
    unit
</div>
<script>

    function getStyle(el, styleProp) {
        var value, defaultView = (el.ownerDocument || document).defaultView;
        // W3C standard way:        if (defaultView && defaultView.getComputedStyle) {
            // sanitize property name to css notation            // (hypen separated words eg. font-Size)            styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
            return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
        } else if (el.currentStyle) { // IE            // sanitize property name to camelCase            styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
                return letter.toUpperCase();
            });
            value = el.currentStyle[styleProp];
            // convert other units to pixels on IE            if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
                return (function(value) {
                    var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
                    el.runtimeStyle.left = el.currentStyle.left;
                    el.style.left = value || 0;
                    value = el.style.pixelLeft + "px";
                    el.style.left = oldLeft;
                    el.runtimeStyle.left = oldRsLeft;
                    return value;
                })(value);
            }
            return value;
        }
    }
    document.addEventListener("keydown", handleInput, false);
    function handleInput(e){          //메인함수
        var keyCode = e.keyCode;

        var pressDispatcher = {       //command dispatcher            37 : new LeftCommand,
            38 : new UpCommand,
            39 : new RightCommand,
            40 : new DownCommand,
            89 : new RedoCommand,
            90 : new UndoCommand        };

        var button = pressDispatcher[keyCode];
        var isPress = (keyCode in pressDispatcher);
        if(isPress) button.execute();


    };

    var Command = function(){
        var x = unit().x, y = unit().y;
        return {
                "execute" : function(){

                    console.log("origin command execute");
                },
                "undo" : function(){
                    if(this.beforeLocation.length > 0){
                        var locationData = this.beforeLocation.pop();
                            unit().move(locationData);
                            this.redoHistoryWrite(locationData);
                    }
                },

                "redo" : function(){
                    if(this.afterLocation.length > 0){
                        var locationData = this.afterLocation.pop();
                        unit().move(locationData);
                        this.undoHistoryWrite(locationData);
                    }
                },
                'beforeLocation' : [],
                "undoHistoryWrite" : function(){

                    this.beforeLocation.push([unit().x,unit().y]);
                },

                'afterLocation' : [],
                "redoHistoryWrite" : function(){

                    this.afterLocation.push([unit().x,unit().y]);
                }
            };
    }();


    function RedoCommand(){

        function _RedoCommand(){
            this.execute = function(){
                this.redo();
            };

        }
        //@extends        _RedoCommand.prototype = Command;

        if(!(this instanceof _RedoCommand )){
            return new _RedoCommand();
        }
    }


    function UndoCommand(){

        function _UndoCommand(){
            this.execute = function(){
                this.undo();
            };

        }
        //@extends        _UndoCommand.prototype = Command;

        if(!(this instanceof _UndoCommand )){
            return new _UndoCommand();
        }
    }

    function UpCommand(){

        function _UpCommand(){

            this.execute = function(){
                this.undoHistoryWrite();
                up();
            };

        }
        //@extends        _UpCommand.prototype = Command;

        if(!(this instanceof _UpCommand )){
            return new _UpCommand();
        }
    }


    function DownCommand(){

        function _DownCommand(){
            this.execute = function(){
                this.undoHistoryWrite();
                down();
            }
        }
        //@extends        _DownCommand.prototype = Command;

        if(!(this instanceof _DownCommand )){
            return new _DownCommand();
        }
    }


    function LeftCommand(){

        function _LeftCommand(){
            this.execute = function(){
                this.undoHistoryWrite();
                left();
            }
        }
        //@extends        _LeftCommand.prototype = Command;

        if(!(this instanceof _LeftCommand )){
            return new _LeftCommand();
        }
    }


    function RightCommand(){

        function _RightCommand(){
            this.execute = function(){
                this.undoHistoryWrite();
                right();
            }
        }
        //@extends        _RightCommand.prototype = Command;

        if(!(this instanceof _RightCommand )){
            return new _RightCommand();
        }
    }


    function unit(){
        var target = document.getElementById('unit');

        return {
            "x" : parseInt(getStyle(target,"left"),10),
            "y" : parseInt(getStyle(target,"top"),10),
            "body" : target.style,
            "move" : function(arr){
                target.style.left = arr[0]+"px";
                target.style.top = arr[1]+"px";

            }
        };
    }
window.onload= function(){
    /*console.log(unit().x);*/};


</script>

<script>



function up(){
    var target = unit().y;
    return unit().body.top = suffixValue(target, -3);
}

function down(){
    var target = unit().y;
    return unit().body.top = suffixValue(target, +3);
}

function left(){
    var target = unit().x;
    return unit().body.left = suffixValue(target, -3);
}

function right(){
    var target = unit().x;
    return unit().body.left = suffixValue(target, +3);
}

function suffixValue(target, value){
    var suffix = "px";
    return (target + value)+suffix;
}

</script>
</body>
</html>

2016년 2월 25일 목요일

[classic asp] 엑셀에서 alt+enter 값 추가

개행문자에 대해서 치환을 해줄때 그냥 <br />을 넣어줄경우 밑에 셀로 한개 한개씩 생김
br 스타일에 <br style='mso-data-placement:same-cell;'> 이런식으로 넣어주면
alt+enter 값 들어간거처럼 들어감

2016년 2월 22일 월요일

추상 팩토리 패턴 (abstract pattern)


추상 팩토리 패턴(Abstract factory pattern)은 다양한 구성 요소 별로 '객체의 집합'을 생성해야 할 때 유용하다. 이 패턴을 사용하여 상황에 알맞은 객체를 생성할 수 있다.
대표적인 예로, 자바 프로그래밍 언어의 GUI 구성 요소인 AWT/Swing 라이브러리의 룩 앤드 필 변경 기능을 들 수 있다. 메탈마이크로소프트 윈도맥 OS 등의 모양으로 변경할 수 있다. 이에 따라 추상 팩토리에 있는 기본 팩토리 객체가 변경된다. 그러면 이후로 생성되는 GUI 객체들은 전부 해당 룩앤필에 따른다.

------------------------------------------------------
다이어그램 

abstract factory ---> abstract product
        ↑                          ↑
concrete factory ->   concrete product

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

다이어그램 구상

가상공장   ---> 차, 신발, 시계 등등 공장 제품 
   ↑                 ↑   
  공장      ->      완제품

------------------------------------------------------
구현 

<!doctype html>
<html lang="ko">
 <head>
  <title>abstract factory</title>
 </head>
 <body>
 <script>
 // 공장에서 여러 제품들을 만든다고 생각 하면 쉬움 
 
  var AbstractFactory ;  // 추상화된 공장(생산, 이름 등등의 기능 을 갖고 있을거임)
  var ConcreteFactory ;  // 구현된 공장(실질적 공장의 이름과, 작동에 대해 기술되 있을거임)
  var AbstractProduct ;  // 공장에서 생산할 제품들의 추상화된 인터페이스 (차, 시계, 신발 등등)
  var ConcreteProduct ;  // 해당 제품을 공장에서 만든다 생각 

  AbstractFactory = function(){
   this.location ='서울';
   this.companyName = 'nice';
  }; 

  AbstractFactory.prototype = {
   create : function(){
    console.log(this.product);
   },
   set : function(product){
    this.product = product.name;
   }
  };

  function ConcreteFactory(){
   var abstractFactory = new AbstractFactory
    abstractFactory.location = '경기';
    abstractFactory.companyName = 'nic';

   return abstractFactory;
  }

  function AbstractProduct_car(){
   this.name = 'car';
  }

  function AbstractProduct_shoes(){
   this.name = 'shoes';
  }


  var concreteProduct = new ConcreteFactory;
  var car = new AbstractProduct_car;
  var shoes = new AbstractProduct_shoes;
   concreteProduct.set(car);
   concreteProduct.create();
   concreteProduct.set(shoes);
   concreteProduct.create();
  


 </script>
 </body>
</html>

룩앤필(look and feel)

룩 앤드 필(Look and feel)은 마케팅, 브랜딩, 상표화와 같은 분야와 제품의 내용에 쓰이는 용어로, 사용자의 제품 체험과 겉모양, 인터페이스의 주된 기능을 나타낸다.
소프트웨어 디자인에서 룩 앤드 필은 그래픽 사용자 인터페이스의 관점에서 쓰이며 색, 모양, 레이아웃, 글꼴(룩)뿐 아니라 단추, 상자, 메뉴와 같은 동적인 요소의 동작(필)을 수반하는 디자인의 측면을 이루고 있다. 룩 앤드 필은 또한 API의 관점을 가리키기도 하며, 이 API의 관점 중 대부분은 기능적인 특성과 관련되어 있지는 않다. 룩 앤드 필이라는 용어는 소프트웨어웹사이트 두 곳에서 쓰인다.
룩 앤드 필은 다른 제품에도 적용할 수 있다. 이를테면, 문서에서 룩 앤드 필은 그래픽 레이아웃(문서 크기, 색, 글꼴 등)과 문체를 일컫기도 한다. 기기 환경에서 룩 앤드 필은 제품 라인의 제어, 디스플레이의 일관성을 일컫기도 한다.

위키 참조
https://ko.wikipedia.org/wiki/%EB%A3%A9_%EC%95%A4%EB%93%9C_%ED%95%84

2016년 2월 21일 일요일

자바스크립트 프록시 패턴(proxy pattern )

UML
[client] ---> [subject](interface) ← [proxy]
                        ↑
                 [real subject]


장점 : 사용자로부터 최적화와 관련내용을 감추어 코드를 단순하게 해준다.
단점 : 실제 객체가 생성되어 있다면, 오버헤드가 됨


proxy(대리자) : real subject로의 참조를 관리하고 접근을 제어한다. real subject가 구현하고 있는 인터페이스를 구현하므로 real subject를 사용하는 것처럼 사용할 수 있다.
subject : proxy와 real subject가 구현하고 있는 인터페이스, 이 인터페이스를 통해 이들이 상호 교환적으로 사용될 수 있다.
real subject : proxy가 대리하고 있는 실제 객체


<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>proxy</title>
 </head>
 <body>
<script>

 var urls = [];
 var image = function(){
  return new proxyimage;
 }; //subject
 var realimage = function(){
  this.getimg = function(){
   console.log(urls);
  };
 }; //
 var proxyimage = function(){
  this.getimg = function(url){
   if (urls.indexOf(url) == -1){ // real subject 로드 여부 판단
    urls.push(url);
   }else{
    return (new realimage).getimg();
   }
  };
 }; //

 var client = new image;
  client.getimg('imgurl return'); //proxy 로드 전 
  client.getimg('imgurl return'); //proxy 로드 후 real subject 로드 
</script>
 </body>
</html>