API는 제공하지 않는 웹사이트에서 데이터를 쓰고 싶을 때에는 웹스크래핑 방식으로 데이터를 많이 들 가져오는데요. nodejs용으로 엄청 편한 라이브러리가 있어서 소개합니다. 예전에 이거 할 때 잘 모르던 꼬꼬마 시절에 html을 불러와서 indexOf같은 걸로 찾아서 substring해서 했던 것 같은데...찾아보니 훨씬 편한 라이브러리들이 많이 있네요.

제가 롯데마트를 주로 애용하는데요. 롯데마트에서 데이터를 다 긁어와서 어제보다 떨어진 상품 목록을 가져오는 기능과 상품가격이 떨어지면 유저에게 푸쉬를 보내는 앱을 만드려고 했는데, 어떤 분이 더 완벽하게 만드셔서...다른 아이템을 제작하기로...-_-

마트 자주 가시는 분들 마트모어 앱 쓰세요! 디게 좋네요!

https://play.google.com/store/apps/details?id=com.mart.trace


그래도 삽질한 것은 정리!!

cheerio 사이트

http://cheeriojs.github.io/cheerio/

cheerio github

https://github.com/cheeriojs/cheerio


예제 코드

코드를 잘 보면 jquery selector를 그대로 쓰는 것을 알 수 있습니다. request 라이브러를 통해서 웹사이트 html을 가져온 다음 cheerio를 이용해 파싱 후 jquery selector를 이용해 그대로 원하는 데이터를 가져오면 됩니다.

var request = require('request');
var cheerio = require('cheerio');

request({
    url: 'http://www.lottemart.com/category/categoryList.do?CategoryID=C001001100010001',
    headers: {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36'
    }
}, function(err, res, html) {
    if (err) {
        console.log(err);
        return;
    }
    var $ = cheerio.load(html);
    var liList = $('#list_prod_1').children('ul').children('li');
    for (var i = 0; i < liList.length; i++) {
        // productId를 가져오기 위함.
        var split = $(liList[i]).find('.pr_price .t_roman > span').attr('id').split('_');
        if (split.length < 2) {
            continue;
        }
        var productId = split[1];
        var price = $(liList[i]).find('#ItemCurrSalePrc_' + productId).text();
        price = price.replace(/,/gi, "");
        var title = $(liList[i]).find('#prodNm_' + productId).val();
        console.log(productId + ':' + title + '(' + price + ')');
    }
});


결과

node test.js 
8808836972445:고향의 향기미(20kg/국내산)(35900)
8804595000023:임금님표 이천쌀(10KG)(35800)
8809001961639:고시히카리(10Kg)(36500)
8808509000420:대왕님표 여주쌀(10kg)(35500)
8808433100029:GAP 철원오대미(10KG)(35000)
8808836972438:고향의 향기미(10Kg)(25000)
8809001740135:황토배기신동진쌀(10Kg)(28000)
8809013191468:금싸라기(10Kg)(28500)
8808433200026:철원평야쌀(10Kg)(30000)
8809001564052:서천농협 순미(20Kg)(58000)
8809088510638:즉석오대미(10KG)(39800)
L000000120009:경기도 김포금쌀 20kg [1,000포한정](49900)


 
Posted by 머드초보
,
 

DBCharmer를 사용하고 있었는데, 더 이상 업데이트를 안한다고 해서 다른 걸 찾다보니 이거 밖에 없네요 레일즈4에서 사용해야 하는데, DBCharmer는 3.X버전밖에 지원하지 않아요. 그래서 옮길 겸 정리!

물론 Replication(Master/Slave) 외에 Shard도 지원하는데, 그냥 여러 개의 Database를 정의하고 그 중 원하는 걸로 쓰게 하는 형식으로 되어있어요. 즉 키별로 샤드를 나누려면 직접 구현해야할 것 같아요. 그냥 Database를 선택해서 쓸 수 있다 정도로만 되어 있는 것 같네요. 샤드는 잘 안해봐서 잘 모르겠지만 대충 그런 느낌이네요.

일단 나의 정리의 목적은 Replication이니까 이것만-_-

젬 깃허브입니다.
https://github.com/tchandy/octopus


1. Master/Slave DB준비

보통은 시스템팀이 있는 회사라면 다 알아서 해주지만 한 번 해보는 것도 나쁘진 않아요. 이거 보고 따라하세요. 두 번 따라하세요-_-
http://oqlid.blogspot.kr/2013/05/mariadb-masterslave-replication-tutorial.html


2. Rails4 프로젝트 생성.

루비와 레일즈는 셋팅이 되어있다는 가정하에...

rails new ReplicationTest


3. Gemfile에 Octopus 및 필요한 것 추가.

Gemfile

gem 'ar-octopus'
gem 'mysql2'

옥토퍼스랑 mysql만 있으면 돼요.


4. database 설정

DBCharmer에서는 database.yml에 master slave를 한단계 더 만들어서 설정해서 한 파일에 다 넣었는데요. 얘는 database.yml에는 마스터디비정보만 넣고, shards.yml파일을 새로 만들어서 slave디비정보를 넣어줍니다.

master는 그대로 database.yml에 설정합니다. 

database.yml

default: &default adapter: mysql encoding: utf8 database: mudchobo username: root password: 1234 host: 마스터주소 port: 3306 pool: 5 timeout: 5000 development: <<: *default test: <<: *default database: mudchobo_test production: <<: *default database: mudchobo_production


slave들은 따로 파일을 만들어서 관리합니다.

config/shards.xml

default: &default adapter: mysql2 encoding: utf8 username: root password: 1234 host: 슬레이브주소 port: 3306 pool: 5 timeout: 5000 octopus: replicated: true environments: - development - production development: slave1: <<: *default database: mudchobo production: slave1: <<: *default database: mudchobo_production

설정은 비슷한데, 멀티 slave를 둘 수 있어서 환경 아래 slave1, slave2 등 여러 개를 두개 되면 select하는 것들에 대해서 알아서 선택해서 접속해서 데이터를 가져옵니다.

replicated: true로 사용해야 가능하고, 혹시 특정 모델에만 리플리케이션을 하고 싶으면 fully_replicated: false를 추가하고, 리플리케이션 허용 하는 것에 대해서는 모델에서 아래와 같이 넣어주면 됩니다.

#This class is replicated, writes to master and reads to slave.
class Cat < ActiveRecord::Base
  replicated_model()
end


5. db migration 생성 및 INSERT SELECT 테스트.

테이블 생성해서 테스트 해봅시다. 모델은 간단히 그냥 dummy라는 테이블을 만들고, name칼럼을 하나 넣어봅시다.

$ rails g model dummy name:string
      invoke  active_record
      create    db/migrate/20150403162358_create_dummies.rb
      create    app/models/dummy.rb
      invoke    test_unit
      create      test/models/dummy_test.rb
      create      test/fixtures/dummies.yml
$ rake db:migrate
== 20150403162358 CreateDummies: migrating - Shard: master ====================
-- create_table(:dummies)
   -> 0.0061s
== 20150403162358 CreateDummies: migrated (0.0062s) - Shard: master ===========

그러면 마스터에 테이블이 하나 생성이 되는데요. 물론 리플이 되어있으면 슬레이브에도 있겠죠. 데이터를 넣어보고 가져와봅시다.

$ rails c
Loading development environment (Rails 4.1.7)
irb(main):001:0> Dummy.create(name: 'fucking')
   (0.3ms)  BEGIN
  SQL (1.2ms)  INSERT INTO `dummies` (`created_at`, `name`, `updated_at`) VALUES ('2015-04-03 16:29:27', 'fucking', '2015-04-03 16:29:27')
   (0.6ms)  COMMIT
=> #<Dummy id: 2, name: "fucking", created_at: "2015-04-03 16:29:27", updated_at: "2015-04-03 16:29:27">
irb(main):002:0> Dummy.find(2)
[Shard: slave1]  Dummy Load (0.6ms)  SELECT  `dummies`.* FROM `dummies`  WHERE `dummies`.`id` = 2 LIMIT 1
=> #<Dummy id: 2, name: "fucking", created_at: "2015-04-03 16:29:27", updated_at: "2015-04-03 16:29:27">
irb(main):003:0> 

잘 되는데....슬레이브에서 가져오는지 잘 모르겠네요... 슬레이브 서버를 죽여버릴까......-_-

irb(main):008:0* Dummy.create(name: 'yes!')
   (1.0ms)  BEGIN
  SQL (0.9ms)  INSERT INTO `dummies` (`created_at`, `name`, `updated_at`) VALUES ('2015-04-03 16:31:55', 'yes!', '2015-04-03 16:31:55')
   (1.2ms)  COMMIT
=> #<Dummy id: 3, name: "yes!", created_at: "2015-04-03 16:31:55", updated_at: "2015-04-03 16:31:55">
irb(main):009:0> Dummy.find(3)
[Shard: slave1]  Dummy Load (0.2ms)  SELECT  `dummies`.* FROM `dummies`  WHERE `dummies`.`id` = 3 LIMIT 1
Mysql2::Error: closed MySQL connection: SELECT  `dummies`.* FROM `dummies`  WHERE `dummies`.`id` = 3 LIMIT 1

아 잘되네요.

그 외에도 slave서버를 선택해서 사용할 수 있는 using메소드도 있어요. 

뭔가 별거 아니지만 장황하게 썼다-_-

PS. 한 프로젝트에서 멀티 디비를 사용하는 프로젝트에서도 유용하게 사용할 수 있어요. 그 Octopus_establish가 있는데, 그걸 통해서 해당 모델에서는 그것에 대한 슬레이브만 접근할 수 있는 설정도 할 수 있어요! 유용하게 쓰세요!

 
Posted by 머드초보
,
 



 스마트폰이 나오고 게임은 모바일 게임만 하고 있는데요. 재미있는 게임들이 많이 나오고 있어서 참 좋은데, 고퀄리티 게임이 아직은 많이 부족하죠. 그나마 인피니트 블레이드가 고퀄리티 그래픽의 게임이였던 것 같네요.

 최근에 EA에서 UFC(?)의 인기에 힘입어 UFC 모바일을 냈습니다. 기존에 콘솔버전도 있었는데 모바일로 나온 것 같습니다. 모바일로 나오면서 모바일에 최적화된 컨트롤를 제공합니다.

아...아직 아이폰 밖에 없어보입니다. 안드로이드도 있는데, 실제 한국에서는 다운 못받게 되어 있네요.


1. 격투 화면

그래픽은 매우 좋습니다!

그냥 상단 터치는 약펀치, 하단 터치는 하단 약펀치 입니다. 그리고 오른쪽으로 드래그를 하면 앞으로 나가면서 펀치! 대각선으로 올리면 어퍼컷, 뒤로 드래그를 하면 회피, 두손가락 터치홀딩은 막기입니다. 어려워보이지만, 하다보면 매우 쉽고 직관적이게 잘 되어 있습니다.

사실 격투할 때에는 제가 해보니까 헤비급은 대충 회피하다가 슬로우로 회피되면 그때 펀치를 때리면 4번 평타를 때릴 수 있습니다. 평타를 계속 때리면 좌측하단에 스킬 케이지가 차는데요. 하나씩 찰 때마다 랜덤으로 스킬을 사용할 수 있게 되며, 총 3개까지 킵해둘 수 있습니다.

그리고 가끔 테이크다운 시키는 기술이 튀어 나오는데, 이걸 시전하다가 걸리면 아래 게이지가 나오는데, 거기에 파란색 영역으로 바가 갈 때 터치를 해주면 걸리게 됩니다. 이게 걸리면 누워서 팰 수 있는데, 누워서 패는 스킬도 따로 있어서 게이지가 찰 때마다 스킬이 차는 것은 같습니다.

가끔 스킬 높은 놈들이랑 싸우면 내가 눕혔어도 이 놈이 헤딩을 하거나 주먹을 잡고 때리면 더 손해보는 경우도 있으니 주의를...-_-

위에 캡쳐한 놈 겨우 잡음 ㄷㄷ


2. 커리어

게임을 시작하면 커리어모드가 뜹니다. 스테이지 형식으로 되어있는데요. 하나하나 격파해나가는 것입니다. 얼추 세어보니 총 200스테이지까지 있군요. 

휴...아직 절반도 못왔네요...


일단 선수를 기본적으로 한 명을 주는데요. "알렉산더 구스타프손" 입니다. 사실 UFC를 안봐서 잘 모르겠습니다. 선수의 등급은 선수의 숫자 옆에 있는 색상으로 구분하는데요. 선수컬렉션에서 제일 비싼 놈이 보라색인 걸로 봐서 보라색 > 파란색 > 흰색 같아 보입니다. 사실 처음에 케릭터 등급이 있는 줄 몰랐....

암튼, 이 선수별로 커리어 스테이지가 200판씩 있는데요. 선수별로 다 깨려면 체급별 선수가 약 20명정도 있으니, 20(선수)x4(체급)x200(스테이지) = 16000스테이지를 깨면 되는 듯... 물론 현질해서 선수를 다 산다는 가정하에...

커리어를 10판정도 깰 때마다 UFC상자를 열 수 있는데, 여기에는 훈련팩 또는 가끔 선수가 나옵니다. 이 훈련팩은 어디에 쓰이냐! 선수를 훈련하는데에 쓰입니다. 선수가 게임을 한다고 해서 레벨업이 되고 그러지 않아요. 훈련팩으로 훈련을 시켜야 선수가 성장합니다.

일단 스테이지 한 판!

아오.. KO시켰어야 했는데...위와 같은 스테이지를 계속 하게 됩니다. 그리고 계속 클리어 해야하죠. 어느 정도 하다보면 상대방 패턴을 파악하게 됩니다. 사실 그냥 회피하고 펀치하고 기가 차서 스킬 생기면 스킬 쓰면 됩니다. 대부분 이런 패턴으로 이길 수 있어요. 지금도 상대방이 체력이 저보다 두 배가 많지만 상대방의 강타격만 조심하면 충분히 이길 수 있습니다.

이기고 나면 소정의 은화를 받습니다. 져도 타격 몇 번 카운터 몇 번 들어갔느냐에 따라서 은화를 받긴 받지만 더 적게 받죠. 이 은화로 할 수 있는 것은 훈련팩과 부스트를 살 수 있는데요. 부스트는 시간이 지나면 모이니 훈련팩을 사는 것을 추천합니다. 훈련에서 가끔 선수도 나오니까 2000은화 모이면 바로바로 뽑으세요. 

그리고 체력 80%이상 남기고 클리어 시 별3개로 은화보너스를 더욱 많이 줍니다. 체력40%이상 남기고 클리어 시에도 별2개로 은화보너스를 줍니다. 그냥 클리어 시에는 별1개만 받게 되는데, 이 때 지난 스테이지를 다시 할 수 있는데, 다시 체력80%이상으로 클리어 하면 골드보너스를 주니, 훈련으로 레벨을 올려서 지난 스테이지를 클리어해서 은화를 버세요!


3. 선수 시스템

체급이 헤비급, 미들급, 라이트급, 플라이급 총 4개급이 있습니다. 처음에 알렉산더밖에 없어서 하나 빼고 다 잠겨 있는데, 훈련팩 계속 까다 보면 선수가 나옵니다. 그 선수들로 미들급, 라이트급, 플라이급을 열 수 있어요. 물론 돈이 많다면 그냥 구매하셔도 됩니다-_- 이걸 여는 게 중요한 게, 체급별로 급여를 받을 수 있는데, 이 급여는 12시간마다 풀이 찹니다. 풀찰 때 체급별 1000은화정도 받을 수 있어요. 그러니 다 열면 12시간마다 4000은화를 벌 수 있어 12시간마다 훈련팩 2개를 공짜로 깔 수 있어요!

뭐 선수를 사는 것은 말리지 않겠습니다만, 굳이 사지 않아도 레어(파란색)정도 선수는 자주 나오는 것 같아요. 선수 가격 개념이 없어서 선수 구매는 비추 ㄷㄷ 헤비급만 다 더해봤는데, 40825골드가 드네요. 40825골드는 약 40만원이면 구매할 수 있네요. EA의 개념없는 BM정책은 UFC에서도 계속 됩니다...

선수는 훈련 시킬 수 있는데요. 선수마다 스킬이 조금씩 다릅니다.

스킬들이 보입니다. 특정 레벨이 되면 스킬들이 열립니다. 30레벨일 때 열리는 것이 마지막인듯염. 확실히 높은 레벨일 때 열리는 스킬들이 타격할 때 쎕니다. 20쯤에서 배운 엘보우 어택은 매우 강력하더군요.

그리고 위에 이미지에서 빛이 나는 스킬이 있는데, 이건 훈련스킬 중에 선수가 가진 스킬과 일치하는 스킬이 있다는 겁니다. 이 일치하는 스킬로 훈련을 하면 경험치가 6배가 됩니다! 

우오오! 한 번에 레벨이 2개나 올랐네요!

이걸 잘 활용해야 선수를 금방 키울 수 있어요. 이렇게 훈련을 하면 레벨 경험치도 상승하고 선수의 능력치인 체력/스탠딩/그라운드 능력도 같이 올라갑니다.


4. 부스트 시스템

부스트가 1칸차는데 거의 2시간쯤 걸리는 것 같은데, 어느 정도 걸리는지 잘 모르겠네요. 겁나 안차는데, 이게 한 경기에 한해서 해당 선수의 스탠딩/그라운드 능력을 상승 시켜 줍니다. 정말 안깨지는 스테이지가 있다면 부스트 모아뒀다가 올인해서 클리어 하면 됩니다. 부스트 10개 썼는데 지면 접고 싶을 듯-_-

부스트은화 2000개로도 살 수 있습니다. 하지만, 은화로 그냥 훈련팩을 사는 게 나아요. 한 스테이지를 깼다해도 분명 다음 스테이지를 못 깰 테니깐요. 


5.  기타 등등

(1)라이브이벤트

아직도 뭐하는 것인지 모르겠습니다. 맨날 들어가면 선택한 라이브 이벤트가 없대요-_-


(2) 친구들

페이스북을 연동하기 때문에 페이스북 친구들이랑 뭔가 할 수 있는 기능이 있습니다. 그냥 친구랑 붙는 건데, 물론 실시간은 아닙니다. 친구스탯으로 그냥 싸우고 이기면 은화를 주는 형식입니다.

성호형님 파워넘버가 너무 약하네...


(3) 빠른 경기

유저 아무나 랜덤으로 붙는 것 같습니다. 뭐 대충 비슷한 실력의 유저들과 매칭 시켜 줍니다. 이기면 마찬가지로 은화를 줍니다.


6. 총평

일단 실시간 대전이 되지 않아서 매우 아쉽네요. 그것만 있었으면 좀 더 괜찮았을 것 같은데, 너무 NPC의 패턴이 비슷합니다. 그래서 능력 대비 약 1.5~2배 정도 되는 애들도 쉽게 잡을 수 있어요. 물론 아직 헤비급만 주로 하고 있고, 다른 체급은 패턴이 좀 다르긴 하더라구요. 그래서 스테이지 클리어 시 약간 지겨울 수 있어요.

그리고 친구랑 뭔가 하는 것이 너무 없네요. 소셜 기능을 너무 안넣었어요. 친구를 도와준다던지 그런 기능이 있었으면 좋았을 뻔 했네요.

하지만, 그래픽만은 정말 최강인 게임이네요. 언젠가 피씨 모바일 구분 없는 게임이 곧 나올 것 같네요.

 
Posted by 머드초보
,