반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

이번주 여기 엄청 춥네요.


오늘 날씨 관련 기사 읽으면서 날씨 관련 영어 몇가지 배웁니다.




Strong wind makes it feel like the temperature has dropped below zero



January 24, 2013 7:14 am
By Jack Perry




PROVIDENCE, R.I. -- A strong northwest wind is making it feel like the temperature has dropped below zero in Southern New England on this Thursday morning.


For example, the temperature is about 6 degrees in Providence, but the 15 to 20 mph wind is making it feel like 6 degrees below zero, according to our weather parnters at WPRI.


In Westerly if feels like 10 degrees below, 9 degrees below in Newport.


The temperature will work its way up to 17 to 21 degrees but the wind chill will remain near zero through the day, according to the forecast by meteorologist Michelle Muscatello.


It will drop down to about 5 degrees again tonight.


For more weather and updates, see providencejournal.com/weather.


The thermometer tells the story in Barrington.



PROVIDENCE, R.I. -- 강한 북동풍이 불어 목요일 오전 남부 뉴 잉글랜드 지방의 체감온도가 0도 이하로 느껴지도록 만들고 있습니다. 

프로비던스의 경우 실제 온도는 6도 이지만 15~20 mph 의 바람으로 인해 - 6도의 체감온도를 보이고 있다고 WPRI 기상정보 제공사는 말하고 있습니다.


서쪽 지역은 체감온두 -10도 그리고 뉴포트지역은 -9도의 체감온도를 보이고 있습니다.


오늘 기온은 17~21도까지 올라가겠으나 바람의 영향으로 하루 종일 0도 내외의 체감온도를 보이겠다고 기상학자인 Michelle Muscatello 는 말합니다.


오늘밤 기온은 다시 5도로 떨어질 것으로 보입니다.


좀 더 자세한 소식이나 최근 업데이트된 날씨 정보를 원하시면 providencejournal.com/weather.를 보세요.

여기서 말하는 기온은 화씨거든요. 저 위의 온도계 사진을 보시면 화씨에서 0도면 섭씨로는 영하 17도 쯤 되는것 같습니다.

그런데 체감온도가 화씨 -10도라면 섭씨로는 영하 23도 정도 되네요.


한국도 이 정도로 춥다고 하는데...


올해는 무척 추운 겨울이네요.


모두들 감기 조심하세요...




반응형


반응형

박근혜가 명예총재로 있었던 사단법인 구국여성봉사단이 경기도로부터 1978년 현재가치로 1500억원대에 이르는  4만3천여평을 불하받았고 이 땅의 매각대금이 어떻게 처리됐는지 의문으로 떠오르고 있다.


Ohmynews 가 단독으로 보도한 기사인데.

박근혜 총재 구국봉사단, 땅 4만3000평 소유했었다

[단독] 1978년 경기도로부터 수의계약으로 불하받아 1979~1980년에 매각


구국 여성봉사단은 1976년 최대민 목사(사이비교주)가 만들었고 이에 박근혜가 명예총재로 참가했었다. 그리고 1978년 박근혜는 총재로 취임했고 1979년 구국여성봉사단은 새마음봉사단으로 이름을 바꿨다.


당시 중앙정보부(부장 김재규)는 최태민 목사에 대한 비리자료를 만들어 박정희에게 보고했었는데 그 자료에 나온 위 부지와 관련된 언급은 아래와 같다.


○ 77. 2. 21 金OO에게 경기도로부터 안양종축장(토지 70,788평, 건물 36동)을 奉仕團(봉사단)명의로 수의계약, 매수하여 준다는 댓가로 동 토지 7,000평과 동 지상건물 36동을 받기로 約束(약속).


당시 박정희는 김재규와 최태민 그리고 박근혜를 모두 불러 이 자료와 관련 대질신문을 했다고 하는데 박근혜는 최태민을 옹호했었다고 함.

김재규가 나중에 최후진술에서 박정희 권력의 부패상을 얘기하면서 이와 관련된 내용도 언급했다고 함.

당시 중앙정보부의 보고 자료 중에는 최태민이 수많은 여성들을 농락한 성희롱, 성폭력과 관련한 자세한 보고 내용도 있었다.

이와 관련한 내용을 보려면 여기를 클릭하세요.

최태민 관련 기사를 더 보시려면


1991년 Inside The World 1월호 "박근혜-최태민 편지 한장이면 돈이 산터미처럼 굴러와"

Ohmynews 최태민 목사 딸 부부 소유 평창 땅 더 있다

그리고  박근혜 올케는 '폐업', 최태민 사위는 '매각'... 왜? 등을 보시면 됩니다.


그리고 이 기사에는 김정렴 전 청와대 비서실장의 회고록 내용도 인용하고 있다.

(관련기사 : "영애 박근혜, 기부금 낸 기업 민원해결 요청")


"육(영수) 여사 서거 후 큰따님 근혜씨가 충효사상 선양운동을 시작했는데 이때 최모(최태민)라는 목사가 '구국선교단'을 조직해서 가세하였다. 하루는 큰따님으로부터 구국선교단을 지원하고 있는 어느 '건설회사'와 '섬유공업회사'의 현안 문제를 해결해주었으면 한다는 이야기를 전해 들었다. 나는 아버지 박 대통령을 돕겠다고 순수하게 충효 선양운동을 시작한 큰따님이 구국선교단에 이용될 위험성이 크다고 생각되어 즉각 박 대통령에 보고했다." (김정렴 회고록 <아, 박정희>)


박근혜는 줄곧 최태민 사이비교주를 옹호하고 결백을 주장했다는데...


박근혜가 대통령으로 당선된 만큼 이런 검은 과거를 제대로 밝혀내고 단절할 기회가 마련됐다는 의미도 있을 것이다.

우리나라를 더 건강하고 밝은 미래로 나아갈 수 있도록 이런 과거의 검은 역사를 제대로 파헤치고 상처를 치유하는 그런 박근혜 대통령이 되기를 진정으로 바란다.


두리뭉실 어물쩍 넘어가서 나중에 악몽의 이명박근혜 정권 10년이란 평가를 받지 않도록....



P.S. 조웅 목사 관련 인터뷰 내용으로 이곳에 오신 분들은 저의 이 글도 참고해 주세요.






반응형


반응형

Facebook Corona TIP



Want to turn off your debug print statements for your production build?


production build에서는 디버그용 print 구문이 실행되지 않도록 하고 싶으세요?


 

Add this little block of code to your main.lua:


main.lua 파일에 아래 코드 블럭을 추가하세요.


 

debugMode = true

cachePrint = print

function print(...)   

if debugMode then       

cachePrint(unpack(arg))   

end

end

 


Then to turn it off, change "debugMode" to false.


print 구문을 출력하고 싶지 않으시면 간단하게 debugMode를 false로 바꿔주시기만 하면 됩니다.




반응형


반응형
Posted on . Written by




이번에 새로운 feature request/feedback 툴 을 소개해 드리게 되서 기쁩니다. 이 툴로 인해 코로나 개발자분들이 필요로 하는 부분에 대해 좀 더 서비스를 제공해 드릴 수 있게 될 것입니다. 지금까지 our forums 는 코로나에 대해 질문할 수 있고 토론할 수 있는 좋은 공간이었습니다. 그리고 앞으로도 계속 그 역할을 할 것입니다. 하지만 어떤 기능에 대한 요구들을 계속 관리(추적)하고 해당 기능의 중요성 같은 것들을 알 수 있는 그런 공간은 아니었죠. 이런 포럼의 부족한 부분을 보완할 수 있는 그런 solution을 갖게 됐습니다.



코로나 Engineering Team 에게 어떤 기능을 요구하고 싶으시면 feedback tool (http://feedback.coronalabs.com)로 가세요 그리고 그 기능에 대해 설명해 주세요. 그리고 난 후 아래 2가지 옵션 중에 한가지를 선택하시면 됩니다.


1) If the auto-search function brings up the feature you want, just vote for it (1 to 3 votes)
2) If you are requesting something new, post the new feature (and vote for it)



short description/comment 도 유용합니다. 특히 이 댓글에 여러분이 이 기능을 어떻게 사용하고 있는지 등을 보내 주시면 더 좋겠습니다. 하지만 이 툴이 discussion 이나 질문을 하는 그런 곳은 아닙니다. 그런 일은 저희  forum에서 진행하는게 더 맞습니다. 이번에 새로 선보이는 툴은 새로운 기능에 대해 제안하는데에 이용해 주세요.



Corona SDK 에서는 해당 기능에 대해 15 votes가 가능합니다. 그러니까 그 vote들을 잘 활용하세요. 이 툴의 목적은 개발자 분들에게 가장 중요한 기능이 어떤 것인지에 대해 알 수 있도록 하는 겁니다. 그러니 아무거에나 vote를 하지 마시고 가장 필요한 기능 순서대로 vote를 해 주세요.



이 툴에 대해서는 나중에 Single sign-on 이 적용 될 계획입니다. (그러니까 그때에는 코로나 account로 접속한 후 사용하셔야 됩니다.) 지금은 vote를 하기 위해 email address 를 입력해 주시면 됩니다. 이 이메일 주소는 다른 목적으로는 사용되지 않습니다. 단지 그 툴에 대한 결과에 대한 답변 메일을 받게 되실 겁니다.


여기까지 입니다. 코로나에서 보고 싶은 기능을 여기로 접속 하셔서 저희들에게 말씀해 주세요. 그러면 그 툴을 모니터해서 그 중요성을 보고 우선순위를 정해서 저희들의 roadmap 에 포함시키겠습니다.


Thanks,


David




반응형


반응형

다음주에 여기 많이 추워지나봐요.

영하 15도까지 내려갈 것 같은데..

아파트에서 한파에 대비해 달라고 메일이 왔네요.

오늘은 그 메일로 영어 공부 했습니다.


Warning! Freeze Notice

***FREEZE WARNING SUNDAY 1/20 – THURSDAY 1/24***


Dear Residents,

입주자 여러분


Due to the predicted severe freezing weather anticipated for this week, water pipes in our community are at risk of freezing. Certain precautions are essential in order to avoid damage to your apartment home and those that surround you. Please take the following precautions as soon as possible.


이번주에 한파가 몰아친다는 예보입니다. 저희 community 내의 수도 파이프가 얼 위험이 있습니다. 여러분의 apartment home 과 그 주변에 피해가 없도록 예방이 필요합니다. 최대한 빨리 아래의 예방조치들을 취해 주시기 바랍니다.



Run a drip of water from all of the faucets in your apartment home. Run both the hot and cold water at a steady drip. Leave the faucets dripping until we remove the Freeze Alert signs at the entrances to the property.


여러분 apartment home 에 있는 모든 수도꼭지를 살짝 열어서 물방울이 떨어지게 해 주세요. 냉수 온수 둘 다 계속 물방을이 떨어지도록 해 주세요. 단지 내에 이 한파 주의보 sign 이 없어질때까지 계속 수도를 약간 열어놔 주시기 바랍니다.



Adjust your thermostat to no lower 60°. Open all closet and cabinet doors to expose plumbing fixtures to the warm air.


난방은 60도 이하로 맞춰놓지 마세요. 모든 클로젯과 캐비넷 문을 열어서 그 안에 있는 파이프들이 외부로 노출되도록 해 주세요. 그래야 온풍이 전달 돼 냉파를 피할 수 있습니다.



If you know that one of your neighbors is away, please contact the Rental Office so we can protect their home. (It is always a good idea to notify the Rental Office if you will be away.)


이웃중에 장기 출타하신 분을 아시면 아파트 사무실에 알려 주세요. 그러면 저희들이 그 집에 조치를 취하겠습니다. (언제든지 장기로 집을 비우실 때는 아파트 사무실에 미리 연락을 주시면 감사하겠습니다.)



Make necessary accommodations for any pets.


애완동물에게도 알맞는 조치를 취해 주세요.



Please remember, the management company is not responsible for any losses incurred from water, windstorm, freezing weather, etc. We recommend that each of our residents maintain renter’s insurance for coverage of damage to personal belongings.


관리 회사는 물과 폭풍, 한파 등과 관련된 피해에 대해서는 책임이 없음을 알려드립니다. 저희는 입주자 여러분께 사유물의 피해를 보상할 수 있는 입주자 보험을 들 것을 권장합니다.



Thank you for your prompt attention.


감사합니다.





반응형


반응형

Ohmynews 의 한 기사를 보다가 갑자기 댓글을 달아야 겠다는 마음이 마구마구 불길처럼 솟았어.


"진보, 안철수 쪽과 손 잡아 제3세력 만들어야"

라는 기사야. 제목 부터가 머리 빡 돌게 만들지 않아?


항상 진보쪽을 지지하는 마음이었고 막상 큰 선거에서는 정권교체를 위해 제1야당 후보를 찍으면서도 언젠가는 자신있게 진보 후보를 찍을 날이 올거라는 기대감으로 20여년간 투표에 참여해 왔는데......

그 동안의 진보의 모습에 너무 실망해서 이젠 그나마 마음속 지지도 접었어.


아래가 그 기사 내용 중 일부인데... 이거 보고 댓글을 안 쓸 수가 없더라구.


"진보정의당이 안철수 현상과 힘을 합쳐 민주당보다 더 혁신적인 정치세력으로, 한국정치를 바꾸는 제3세력으로 성장하면 의미 있다고 본다. 이런 전망이 실현 가능하게 만드는 데는 물론 안철수 진영의 선택이 중요할 것 같다."



아래가 내 댓글이야.


안 철수 현상으로 나타난 국민의 열망은 진보로 향한게 아니다. 그런데 왜 진보가 그걸 받아 안으려 하나? 이 국민의 열망이 진보로 향 할 수 있도록 일을 해야 한다.일도 제대로 안 했는데  다른쪽으로 향한 열망을 받아 안겠다고? 그건 가로채기다. 진보가 가로채 도 계속 열망을 줄것 같나? 안철수는 보수다. 안철수 중심의 보수정당이 만들어져야 한다. 새누리에는 수구만 남아야 한다. 그래 서 그 수구 새누리, 조중동, 기타 무논리 무이념, 눈앞의 이익만 쫒는 수구 부패 세력을 소수로 만들어야 한다. 그러려면 진보 는 대중적 지지를 받아야 된다. 그래야 보수대 진보로 설수 있다. 안그러면 보수대 수구 구도가 될 수도 있다. 난 한마디로 지금 의 국민 열망이 조금이라도 진보에게 향하는게 아깝다. 일단 진보 스스로 서라.


같은 톤의 다른 댓글들도 눈에 띄더라구.


말이좋아 진보지 당신들이 정직한 진보라 양심있게 말할수 있는지.
국민은 이념보다 먼저 정직한 세력을 원한다.
작금의 진보주의자들은 진보라는 단어를 빌려쓴 꼼수의 정치집단체일뿐.
당신들의 행하는 진보는 진보의 울타리에 갖혀있는 편협한 진보다.
그런 진보는 국민에게 지지 못 받는다.
의존적인 진보세력의 정치성 부터 청산하고 
독립적 기반을 튼튼히 만드는것이 우선이지
힘이들고 지치니 이젠 철수형에게 의존하려 하는 당신들
꼼수의 대가들 답다.

아직도 진보 사이드에서 안철수를 놓지못하고 침흘리는거얌?
형편없는 수준의 나으 사견이지만 안철수는 진보가 아냐.
[정직한 사람], [올바르고 온건한 정치인] 뭐 이런 사람이기는하쥐.

5년 후 [포스트 ㅂㄱㅎ]에서는 어차피 군사쿠데타에 기원을 둔 정치세력은
종말이 와서 우리 정치사에서 어떻게든 일단락 지으면서 끝나게 될꺼야.
그 싯점부터 우리나라에서도 비로소 진정한 의미의 [진보], [보수] 구도 개편이
이루어지지않겠우?

그 때 안철수는 [보수] 진영에 설꺼야. 잘하면 온건한 중도보수.
그리고 현재 제대로 된 민주당 일부세력과 진보 진영에서 
진보성향의 당을 만들어 안철수와 선의의 경쟁을 하지않겠어

긍까 민주당 포함해 진보들,
안철수 놔주고 외롭고 무섭겠지만 니들끼리만 
당당히 순례길에 오르면 안돼?



많은 사람들이 이런 생각 가지고 있지 않을까?


극과 극은 통한다고.

극우 꼴통들이 반북을 그렇게 외쳐 대지만 사실 그들이 존재할 수 있는건 북한이 있기 때문이잖아. 그래야 반북을 하니까.

그 반북으로 밥먹고 사는 놈들은 북한이 진짜 필요한 존재일거야.

북한도 사실은 정당성 없는 남한의 정권을 더 선호 하잖아. 그래야 자신들의 정당성을 주장하면서 내부 단속을 효과적으로 할 수 있으니까.


박정희 독재와 전두환 독재를 거치면서 목숨걸고 항거하고 화염병과 짱돌을 던지는 저항을 하는 세력들이 있었지만 ..

그 세력들 저항의 대상 없어지니까 대중성을 잃어버리잖아.

아직도 그 때의 모습을 벗어버리지 못한 진보는 사실 독재를 필요로 하고 있는거야..

즉 독재를 부르고 있는거지.


그래서 난 이제 진보가 싫다.


이명박근혜랑 같이 꺼져버려라.


매트릭스에서 마지막에 주인공 네오가 상대 악을 없애기 위해서 하는 행동은 상대를 죽이는게 아니라 자신을 죽이는거 잖아.


그러니 진보도 죽어라.. 이명박근혜가 사라져 버릴 수도 있으니까.. 진보야 죽어라...

반응형


반응형
Posted on

. Written by


수요일 FAQ 시간입니다. 코로나에서 custom fonts 를 사용하는것과 관련해서 자주 질문되는 것들입니다.

1. How do I load custom fonts?

어떻게 사용하는 platform 에 따라서 폰트들을 load 할 수 있나요?


iOS (iPhone, iPad)


iOS (아이폰, 아이패드) 는 build.settings 파일에 font 파일 이름을 추가하면 됩니다.


    iphone =
    {
        plist =
        {
            UIAppFonts =
            {
                "PTF55F.ttf",
                "AvenirLTStd-Black.otf",
                "SourceCodePro-Black.ttf"
            },
            UIApplicationExitsOnSuspend = true
        },
    }


폰트파일들은 resource 디렉토리에 있어야 합니다. 그래야지 iOS app bundle 로 compile 될 수 있습니다.


Mac


맥은 이 폰트들을 여러분의 시스템 안에 인스톨 해야 합니다. 폰트파일을 더블클릭하시면 Font Book app 이 그 폰트를 인스톨 할 겁니다. Mac 에서는 build.settings 파일에 추가할 것은 없습니다.


Android


폰트 파일이 resource 디렉토리에 있어야 합니다. 그래야 안드로이드 앱 bundle 로 컴파일 될 수 있습니다. 안드로이드에서는 build.settings file에 추가될 것은 없습니다.


Windows


윈도우에 custom font를 인스톨하는 것은 맥에서 인스톨하는 거랑 비슷합니다. 그 폰트를 사용하려면 시스템에 폰트를 인스톨 해야 합니다. 윈도우에서는 build.settings file에 추가될 것은 없습니다.



2. How do I use the custom fonts in my app?


Mac and iOS


맥과 iOS 에서 폰트를 사용하려면 폰트 이름을 명시해야 합니다. (파일이름이 아닙니다.) 해당 폰트의 이름이 무엇인지 알려주는 툴이 있을 겁니다. 제가 찾은 가장 쉬운 방법은 폰트를 load 하고 코로나에게 폰트 이름을 표시하도록 하는 겁니다. 시스템에 해당 폰트를 인스톨 했다면 맥 시뮬레이터에서 아래 코드를 실행해 보세요.


-- Code to have Corona display the font names found
--
local fonts = native.getFontNames()

count = 0

-- Count the number of total fonts
for i,fontname in ipairs(fonts) do
    count = count+1
end

print( "\rFont count = " .. count )

local name = "pt"     -- part of the Font name we are looking for

name = string.lower( name )

-- Display each font in the terminal console
for i, fontname in ipairs(fonts) do
    j, k = string.find( string.lower( fontname ), name )

    if( j ~= nil ) then

        print( "fontname = " .. tostring( fontname ) )
    
    end
end
---------------------------------------------------------


예를 들어 PTF55F는 “PTSerif-Regular” 가 될 겁니다. 바로 이 이름이 해당 폰트를 display 하고 싶을 때 명시해야 할 이름입니다.


CustFont = display.newText( "PTSerif-Regular", 40, 20, "PTSerif-Regular", 24 )

Android


안드로이드에서는 파일 이름이 폰트 이름입니다. (파일의 확장자를 제외한 이름이죠)


CustFont = display.newText( "PTSerif-Regular", 40, 20, "PTF55F", 24 )


안드로이드와 iOS 그리고 맥에서 같은 폰트 이름을 사용할 수 있는 팁이 있는데요. 폰트 파일 이름을 폰트 이름과 같이 하는 겁니다. 그려면 iOS/Mac 그리고 안드로이드에서 같은 이름을 사용할 수 있습니다.


Windows


The font name may be slightly different from Mac/iOS. In come cases spaces are inserted between words in the font name. In the PT Serif example, the font name is “PT Serif”. You can run the code snippet listed under the Mac and iOS section to get the exact name.

폰트 이름은 MAC/iOS 와는 약간 다릅니다. PT Serif 를 예를 들면 폰트 이름은 "PT Serif" 입니다.


CustFont = display.newText( "PTSerif-Regular", 40, 20, "PT Serif", 24 )


아래 예제는 각 플랫폼에 대해 폰트를 사용하는 예제입니다.


if "Win" == system.getInfo( "platformName" ) then PTSERIF = "PT Serif" elseif "Android" == system.getInfo( "platformName" ) then PTSERIF = "PTF55F" else -- Mac and iOS PTSERIF = "PTSerif-Regular" end CustFont = display.newText( "PTSerif-Regular", 40, 20, PTSERIF, 24 )


3. I’ve loaded the fonts but the fonts didn’t load. What’s wrong?


안드로이드와 윈도우즈에서는 폰트를 로드하지 못할 때는 터미널에 경고 메세지가 뜰겁니다.“WARNING: Could not load font xyz. Using default.”. iOS 와 맥에서는 로드를 하지 못했을 때 아무런 메세지도 뜨지 않습니다.

폰트를 로드하지 못하는 두가지 흔한 이유는 시스템이 로드되지 못한경우라던가 (윈도우나 맥) display.newText api에 잘못된 폰트 이름을 사용했을 경우 입니다. 윈도우와 관련해서 추가적으로 알아야할 것이 있는데 그 내용은 아래 질문 4에서 확인하세요.


4. Are OTF (Open Type Font) fonts supported in Corona?


OTF fonts는 맥과 iOS 에서 지원됩니다. 안드로이드는 build 984 후부터 지원하기 시작했습니다. 윈도우에서는 지원하지 않습니다. True Type Fonts (TTF) 는 모든 플랫폼에서 지원합니다.


5. What are the advantages of using Custom Fonts?


일단 custom font를 사용하면 더 이쁘거나 아니면 더 눈에 띄거나 앱에 더 잘 어울리거나 하겠죠. 그리고 또 다른 장점은 모든 플랫폼에서 text placement 의 일관성을 유지할 수 있습니다. 디폴트 폰트를 사용하면 각 플랫폼들마다 폰트가 다를수 있습니다. 그러면 폰트들 크기가 달라서 폰트들의 위치가 약간씩 다를 수 있습니다. custom font 를 사용하면 좀 더 쉽게 font placement 의 일관성을 지킬수가 있죠. 


여기까지가 오늘의 questions 입니다. 좋은 시간 되셨길 바랍니다.



반응형

코로나에서 time, date 다루기

2013. 1. 18. 06:49 | Posted by 솔웅


반응형
Posted on . Written by

“Time keeps on slippin’, slippin’, slippin’, into the future.” —Steve Miller Band / Fly Like An Eagle


어떤 프로그래밍 언어로 time 관련해서 작업을 하는 것은 프로그래머에게 혼란을 주게 됩니다. 이번주의 튜토리얼은 time 과 date 에 대해 다룹니다. 그리고 date 계산, time zone 문제 그리고 date formatting 관련해서 예제를 보여드리겠습니다.


코드를 보기전에 먼저 이해해 둬야할 몇가지 중요한 개념들이 있습니다. 컴퓨터에게는 time 의 기본 유닛은 1초 입니다. 이 값으로 우리는 date 도 계산할 수 있고 fraction 들도 다루고 심지어 time 의 더 작은 순간들도 계산해 냅니다. 사람에게 1초는 짧은 시간이지만 컴퓨터에게는 아주 긴 시간입니다. 사람들도 긴 시간의 경우 세분화해서 사용하듯이 컴퓨터도 마찬가지 입니다. 어떤 함수는 1/1000 초(milliseconds ) 단위로 작업을 하고 이것을 uSec 나 uSeconds으로 쓰기도 합니다. 더 좋은 컴퓨터는 이것보다 더 짧은 시간을 다루기도 합니다. 코로나에서는 3가지 종류의 time measurement 를 사용합니다.




Microseconds and Milliseconds


Microseconds 는 아래와 같이 call 하시면 됩니다 :


system.getTimer()


이 call은 여러분의 app 이 시작한 이후의 시간을 return 해 줍니다. 그 값은 milliseconds (1/1000ths) 단위 입니다. 대부분의 device들에서는 아래와 같은 값을 return 할 겁니다.


1839.3949


이 time은 microsecond resolution 으로 측정되는데요 여러분에게 보일 때는 milliseconds 로 변환해서 보여드리는 겁니다. 그리고 소숫점 아래는 microseconds 를 나타내죠. 이 마이크로세컨드 단위가 필요한 경우가 있을지 궁금해 하실수도 있습니다. 아마 실제로는 필요가 없겠죠. 아마 GPS 데이터를 다루거나 Einstein’s Pedometer (앱 이름인데요. 여러분이 빠르게 움직이면 얼마나 젊어지는지를 보여주는 앱입니다.) 작업을 하게 되면 이 microsecond resolution 이 필요할 수도 있습니다. 하지만 우리의 앱에서는 1초당 30~60 프레임을 사용할 거니까 1/30 에서 1/60 초 단위로 작업을 하게 될 겁니다. 그러니까 1/1000 초 보다 더 정교한 시간계산은 이 앱에서는 그다지 중요하지는 않습니다.


milliseconds와 관련해서 사용하는 함수들은 아래와 같습니다.


이 함수들은 millisecond 단위를 accept 합니다. 그러니까 이 함수에 값을 5000을 주면 그 시간은 5초가 되는 겁니다. 1/2 초는 500이 되겠죠. 2와 1/2 초는 2500이 됩니다.


timer.performWithDelay(500, someFunction)  -- a half second delay


초를 원하는 값으로 바꾸시려면 1000을 곱하면 되겠죠.


Dealing With Longer Periods of Time


위에서 언급했듯이 컴퓨터에서 time 의 기본적인 유닛은 1초입니다. iOS와 안드로이드 (Mac OS X 도 마찬가지로) 모두 Unix 에서 파생된 운영체제에 근거해 있습니다. 그리고 그런 운영체제에서 표준 "time" 함수는 1970년 1월 1일 자정 이후부터 경과된 시간을 초단위로 return 해 줍니다.  마이크로소프트는 좀 다른데요, 하지만 이미 많은 앱들이 C언어를 사용해서 만들어졌고 이 언어는 Unix 에 기반해 있거든요. 그리고 그 언어의 라이브러리도 이 time reference pointEpoch를 사용하구요.


마이너스일 경우에는 1970년 이전이 되겠죠. positive times 일 경우에는 1970년 이후가 되겠구요. 코로나에서는 os.time() API call을 사용해서 1970년 1월 1일 이후 지금까지의 number of seconds 를 얻을 수 있습니다.


print( os.time() )  -- outputs something like: 1358015442


사실 저 숫자만 나온다면 알아볼수가 없으니까 별로 의미가 없겠죠. 이것을 date math로 계산해서 실제 생활에서 쓰이는 날짜와 시간으로 바꿔야 알아볼 수가 있을 겁니다. 그런데 게임을 한번 생각해 보세요. turn-based game 이 있는데 유저가 너무 오랫동안 게임을 하고 있어서 어떤 "nudge" 가 필요한 경우 아래와 같이 마지막 move의 시간을 저장할 필요가 있을 겁니다.


player[1].lastMove = os.time()

그리고 나서 지난 한시간 동안 어떤 move 가 있는지 체크하고 싶으면 아래와 같이 하시면 됩니다.


local now = os.time()
if ( now > player[1].lastMove + 3600 ) then
  -- nudge the player
end


3600은 어디서 왔을까요? 60초 곱하기 60분을 하면 그 값입니다. 즉 1시간이죠. 그러니까 아래와 같이 하셔도 됩니다.


local now = os.time()
if ( now > player[1].lastMove + (60 * 60) ) then
  -- nudge the player
end

Lua 의 pre-processor 는 (60*60) 를 3600으로 convert 할겁니다. 그러면 여러분이 따로 미리 계산할 필요는 없겠죠. 아래와 같이 미리 날짜, 시간, 분을 상수로 정의해서 사용하셔도 됩니다.


DAY = 24 * 60 * 60
HOUR = 60 * 60
MINUTE = 60

local now = os.time()
if ( now > player[1].lastMove + HOUR ) then
  -- nudge the player
end


이렇게 초단위로 다룬 값으로 date math 를 사용하는 것은 아주 쉽습니다.


  • Is your time older than a week? Use ( 7 * 24 * 60 * 60 ).
  • Set an alarm in 30 days? Use ( 30 * 24 * 60 * 60 ).


또한 한달에 몇일이 있는지, 윤년인지 아닌지 등등도 계산할 것을 걱정하지 않으셔도 욉니다.

Working With Dates


Dates(날짜)와 관련해서는 조금 신경을 쓰셔야 됩니다. 왜냐하면 날짜를 표시할 때는 strings 를 사용하니까요.


  • April 1, 2010 4:53pm
  • April 1, 2010 4:53 P.M.
  • 4/1/10 16:53 MT
  • Sun Jan 13 15:17:32 EST 2013
  • 13-JAN-13 15:17


개발자로서 날짜를 component values로 parse 할 필요가 있습니다. date/time string의 각 파트별로 get 하셔야 합니다. (month, day, year, hour, minute, seconds and time zone). 만약에 month를 string 으로 가지고 있다면 이 string 을 number 로 그리고 timestamp로 convert 할 lookup table 을 사용하실 수 있습니다.


local monthNumbers = {}
monthNumbers["January"] = 1
monthNumbers["February"] = 2
monthNumbers["March"] = 3
--etc...
monthAsInteger = monthNumbers[monthString]


가장 일반적인 date format 중의 하나는 ISO-8601 time format입니다. 그 string 값은 대충 아래와 같습니다.


2012-01-12T12:04:35.03-0400


이 date 를 parse 하시려면 이 여러 bit들을  패턴을 사용한 각각의 값으로 break down 하기 위해 string:match string function 을 사용할 겁니다.


local pattern = "(%d+)%-(%d+)%-(%d+)%a(%d+)%:(%d+)%:([%d%.]+)([Z%p])(%d%d)%:?(%d%d)"
local year, month, day, hour, minute, seconds, tzoffset, offsethour, offsetmin =
  dateString:match( pattern )

Lua 를 처음 접하시는 분들 에게는 위 코드가 많이 복잡하게 보일 겁니다. 신택스가 그렇게 간단하지는 않죠? 이해하기 쉽도록 break down 해 보죠.


2012-01-12   T   12:04:35.03   -0400


T 이전 부분은 date 입니다. 알아보기 쉽고 또 나누기 쉽죠.  연,월,일이 숫자로 있고 각각 hyphen 으로 나눠져 있습니다. T는 시간 부분이 시작한다는 의미입니다. 그 다음에는 시,분,초를 가리키는 숫자들이 나오고 각각 colon들로 나눠져 있죠. 이 중 초단위는 floating point number 라는 것을 기억해 두세요. 그 다음부분에는 옵션으로 time zone이 나옵니다. 이 timezone 과 관련해서는 조금 더 얘기를 나눌 겁니다.


string:match() function은 어떤 패턴을 보여주는데요. string 의 span 에 대해 “wildcard” type searching 을 사용하는 그런 패턴이죠. 위의 경우에는 %d+ pattern을 상요해서 숫자를 찾고 있습니다. 이렇게 함으로서 Lua 에게 0에서 9까지의 숫자열을 찾도록 만들죠. + 표시는 한개 이상의 숫자열을 찾는 다는 것을 알려 주는 겁니다. 예를 들어 2012 같은 숫자열을요.


이 값들을 알아볼 수 있는 변수에 저장하기 위해 괄호 () 안에 어떤 pattern set들을 넣게 됩니다. 그러면 Lua에게 우리가 retrieve 하기 원하는 date/time 의 각각의 단위들을 알려줄 수가 있습니다. date 부분은 hyphen 들이 있는데요. 이것은 각 컴포넌트를 분리하는 기호입니다.


(%d+)%-(%d+)%-(%d+) -- gets the year, month and day
%a -- handles the single letter T
(%d+)%:(%d+)%:([%d%.]+) -- gets the hour, minutes and seconds



마지막 부분을 보세요. 숫자하고 점(.) 이 있죠? 초가 floating point value 이기 때문에 이렇게 찾는 겁니다. string matching에서 점(.) 은 “magic character” 입니다. 이 점 앞에 % 를 넣으셔야 Lua 는 실제 점(.) 을 찾을 겁니다.


마지막으로 + 나 - 구분자 다음에 timezone 정보가 옵니다. 혹은 Z 나 UTC 를 사용하기도 하죠. string:match function 은 각각의 match 되는 패턴들에 대한 값들을 return 할 겁니다. 그리고 그 값들을 변수에 담게 되죠. ISO-8601 standard는 timezone time 을 +/-HHMM+/-HH:MM를 사용합니다. 만약 이 timezone 정보가 없으면 여러분이 속해 있는 local timezone 을 사용할 겁니다. 아래의 패턴은 좀 복잡해 보이긴 하는데요. timezone 정보를 처리하는 코드 입니다.


([Z%p])(%d%d)%:?(%d%d)


Z 나 punctuation character 인 + 나 - 다음에 %p가 옵니다. 그 다음에는 두자리 숫자가 와야 됩니다. 그 다음에 colon 은 옵션인데요. 두개의 숫자가 더 올 수도 있습니다. 이 패턴은 tzoffset, offsethour, offsetmin등을 return 합니다. 이것을 date math 에서 사용할 숫자로 convert 하기 위해 os.time() function (documentation) 을 사용합니다.


local timestamp = os.time(
  {year=year, month=month, day=day, hour=hour, min=minute, sec=seconds} )



이제 1970년 1월 1일 이후 몇초가 경과했는지에 대한 값을 갖게 됐습니다. 그리고 이것을 date math 로 이용할 수 있게 됐구요. 한가지 문제가 있는데요. 아직까지 timezone 부분에 대해 일을 마치지는 않았습니다. 다행히 그 작업은 어렵지 않은데요. 지금 이미 기본 시간을 seconds 로 갖고 있으니까 계산만 하면 되곘죠. Z는 time 이 Coordinated Universal Time (UTC)라는 것을 가리키는 겁니다. 만약 이것이 UTC 나 local time 이라면 따로 timezone 과 관련해서 작업할 것은 없습니다.


local offset = 0
if ( tzoffset ) then
  if ( tzoffset == "+" or tzoffset == "-" ) then  -- we have a timezone!
    offset = offsethour * 60 + offsetmin
    if ( tzoffset == "-" ) then
      offset = offset * -1
    end
    timestamp = timestamp + offset
  end
end


os.time()은 여러분이 있는 곳의 timezone 을 사용해서 값을 return 할 겁니다.


아래 코드는 여러분이 라이브러리로 사용할 수 있는 샘플 예제 입니다.


function makeTimeStamp(dateString)
  local pattern = "(%d+)%-(%d+)%-(%d+)%a(%d+)%:(%d+)%:([%d%.]+)([Z%p])(%d%d)%:?(%d%d)"
  local year, month, day, hour, minute, seconds, tzoffset, offsethour, offsetmin =
    dateString:match(pattern)
  local timestamp = os.time(
    {year=year, month=month, day=day, hour=hour, min=minute, sec=seconds} )
  local offset = 0
  if ( tzoffset ) then
    if ( tzoffset == "+" or tzoffset == "-" ) then  -- we have a timezone!
      offset = offsethour * 60 + offsetmin
      if ( tzoffset == "-" ) then
        offset = offset * -1
      end
      timestamp = timestamp + offset
    end
  end
  return timestamp
end


Final note:  여기서는 아직 Daylight Savings Time(써머타임)을 적용하지는 않은 상황입니다. Daylight Savings Time 은 이 튜토리얼에서 다루지 않습니다.


Converting a Timestamp to Something Readable


어떤 경우에는 이 time 을 유저가 알아볼 수 있는 date string으로 표현할 필요가 있을 겁니다. 이게 바로 os.date() function의 목적이죠. (documentation).


os.date() function 은 두개의 파라미터를 받습니다. 둘 다 옵션인데요. 이 옵션 없이 call 하면 현재 있는 지역의 timezone 에 맞는 date/time 을 return 할 겁니다. 아마 아래와 같은 형식일 겁니다.


Sat Jan 12 14:07:30 2013


아주 다양한 형식으로 표현할수 있는데요. 다양한 formatting parameter 들을 이용하시면 됩니다. 이 format parameter들은 Unix/C++ library function strftime에 근거합니다.


print( os.date("%A") )  -- prints out a string representing the weekday.
print( os.date("%A %l:%M%p") )  -- prints out "Saturday 2:30PM"

디폴트로 os.date()가 return 하는 값은 여러분의 지역이나 time zone 에 근거할 겁니다.  RSS feeds, Corona Cloud date 등에서 일반적으로 사용하는 위에서 사용한 날짜 형식을 생성하기 원하신다면 UTC 에 근거한 output 을 받아야 합니다. 이것은 format parameter 앞에 ! 를 붙이시면 됩니다.


print( os.date("%FT%X%z") )  -- outputs: 2013-01-12T15:30:09-0500

or if you wanted it in UTC:

print( os.date("!%FT%XZ") )  -- outputs: 2013-01-12T19:30:09Z



strftime에 있는 다양한 formatting parameter 들은 다양한 format 으로 month, day, year, weekday, am/pm를 얻을 수 있도록 합니다. 



Counting Down Time


흔히 하는 질문으로 "어떻게 countdown timer 를 만들수 있죠?" 가 있습니다.

가장 좋은 방법은 직접 한번 구현해 보는 걸겁니다. 만약에 60안에 한 레벨을 끝내기를 원한다면 60초 후에 뭔가 이벤트를 발생시키기 위해 timer.performWithDelay()를 사용하시면 됩니다. 보기 좋은 UI output 과 함께 좀 더 그럴듯한 방법을 원하신다면 enterFrame event 에 Runtime listener를 사용하실 수도 있습니다. 그렇게 하면 시간을 체크할 수 있습니다. 혹은 1초 timer 를 계속 반복할 수도 있겠죠. 그럼 필요할 때 쉽게 pause 시키고 또 resume 시킬 수 있을 겁니다.


-------- RUNTIME METHOD --------
local startTime = os.time()
local levelTime = 60
local displayTime = display.newText(levelTime, 0, 0, "Helvetica", 20)

local function checkTime(event)
  local now = os.time()
  displayTime.text = levelTime - (now - startTime)
  if ( now > startTime + levelTime ) then
    -- code to end the level
  end
end
Runtime:addEventListener("enterFrame", checkTime)
-------- REPEATING TIMER METHOD --------
local levelTime = 60
local displayTime = display.newText( levelTime, 0, 0, "Helvetica", 20 )

local function checkTime(event)
  levelTime = levelTime - 1
  displayTime.text = levelTime
  if ( levelTime <= 0 ) then
    -- code to end the level
  end
end
timer.performWithDelay( 1000, checkTime, levelTime )



In Summary


Corona에서 time 과 date를 다루는 것은 약간 복잡한 신택스를 다뤄야 합니다. 이 튜토리얼이 그것을 이해하는데 도움이 되셨으면 합니다. 위의 예제들을 활용해서 앱 개발시 이용하시면 훨씬 수월하실 겁니다.


반응형


반응형

어제 이곳 로드 아일랜드 뉴스에는 동성결혼에 대한 얘기가 한창 이슈였습니다.

올해 이곳에서 동성결혼을 허용하는 법안을 만들 것인가 여부가 주의회에서 논의가 시작됐거든요.


이곳에 오기 전에 있었던 뉴저지도 동성결혼 허옹문제가 의회에서 논의되고 공화당 소속 주지사인 크리스티는 이 법안이 통과 되면 거부권을 행사하겠다고 발표하기도 하면서 좀 시끄러웠는데.. 여기도 그러네요.


이곳 New England 지역의 6개 주인 메인, 뉴햄프셔, 버몬트, 메사추세츠, 로드 아일랜드, 코네티넛 중 메인, 코네티컷, 메사추세츠, 뉴 햄프셔, 버몬트는 이미 이 동성 결혼이 법적으로 허락되 있고 로드 아일랜드만 관련 법안이 없는 상황입니다.


하지만 로드 아일랜드도 다른 법에 의해서 실제로 동성 결혼은 이뤄지고 있다고 하는데요. 이번에 제대로 동성 결혼 허용하는 법안에 대해 논의 한다고 합니다.


뉴스에서는 same sex marriage 라고 하는데 이 Providence Journal 에서는 gay marriage 라고 하네요.


기사의 뉘앙스로 봐서는 약간 동성결혼에 대해 긍정적이지는 않은 신문사인것 같습니다.


Nearly 200 opponents of gay marriage rally at R.I. State House


January 15, 2013 5:06 pm
By Philip Marcelo



Providence Journal photo / Philip Marcelo


R.I. Sen. Harold Metts of Providence speaks at the rally in the rotunda Tuesday afternoon.



PROVIDENCE, R.I. -- Opponents of gay marriage are rallying in the State House rotunda Tuesday afternoon, as state lawmakers convene the first hearing on this year's bill to allow gay couples to marry in Rhode Island.


게이 결혼에 반대하는 시위가 주정부 건물인(도청) rotunda 에서 화요일 오후에 있었다. 이날 주 의원들은 Rhode Island 에서 올해 게이 결혼 (동성결혼)을 허락할지에 대한 법안 심사를 하는 첫 날이었다.


With nearly 200 in attendance, church leaders announced a new coalition that is meant to serve as a counterpoint to "Rhode Islanders United for Marriage," which was announced Monday by gay marriage supporters.


200여명이 참가하였고 교회 지도자들은 월요일 게이 결혼(동성결혼) 지지자들이 발표한 "Rhode Islanders United for Marriage 에 대항한 새로운 연대를 발표했다.


The group -- "Faith Alliance to Preserve the Sanctity of Marriage as Established by God" -- includes representatives from the Catholic Church, the Knights of Columbus, the National Organization for Marriage and a number of Hispanic and Latino church groups.

Organizers said the alliance's purpose is to "safeguard God's covenant and definition of marriage." It does not seek to judge or condemn gay, lesbian, or transgender individuals.

More on R.I's gay marriage debate


"신에 의해 만들어진대로 결혼의 신성함을 보존하기 위한 믿음 연합" 이라는 이 단체는 카톨릭, Knights of Columbus, National Organization for Marriage, 그리고 일부 중남미계 교회 그룹으로 구성돼 있다. 이 단체 설립자들은 이 연합의 목표는 신과의 약속과 결혼에 대한 정의를 지키는 것이라고 말했다. 게이, 레즈비언 혹은 트랜스잰더들을 개별적으로 심판하기 위한 단체는 아니다.

More on R.I's gay marriage debate






반응형


반응형

이번에는 getTextUsingTransformations() 함수를 살펴볼 차례죠?


제 생각에 오늘로 소스 분석이 모두 끝날 것 같습니다.

사실 제가 할 작업은 지금까지 분석한 것으로도 충분하거든요.

벌써 미팅에서 결과를 공유했고 그 다음 단계가 진행중입니다.


하지만 시작했으니 마저 끝마쳐보죠.


pdf2text() 함수의 맨 마지막 return 문에 있는 코드 입니다.


return getTextUsingTransformations($texts, $transformations);


파라미터로는 getDirtyTexts() 함수에서 얻었던 $texts 가 첫번째에 있네요.

이 내용은 지난 글 말미에 보여드렸습니다.


두번째 파라미터는 getDecodedStream() 함수를 통해서 얻었던 $data 입니다.


getTextUsingTransformations($texts, $transformations) 함수를 볼까요?


function getTextUsingTransformations($texts, $transformations) {
    $document = "";
    for ($i = 0; $i < count($texts); $i++) {
        $isHex = false;
        $isPlain = false;

        $hex = "";
        $plain = "";
        for ($j = 0; $j < strlen($texts[$i]); $j++) {
            $c = $texts[$i][$j];
            switch($c) {
                case "<":
                    $hex = "";
                    $isHex = true;
                break;
                case ">":
                    $hexs = str_split($hex, 4);
                    for ($k = 0; $k < count($hexs); $k++) {
                        $chex = str_pad($hexs[$k], 4, "0");
                        if (isset($transformations[$chex]))
                            $chex = $transformations[$chex];
                        $document .= html_entity_decode("&#x".$chex.";");
                    }
                    $isHex = false;
                break;
                case "(":
                    $plain = "";
                    $isPlain = true;
                break;
                case ")":
                    $document .= $plain;
                    $isPlain = false;
                break;
                case "\\":
                    $c2 = $texts[$i][$j + 1];
                    if (in_array($c2, array("\\", "(", ")"))) $plain .= $c2;
                    elseif ($c2 == "n") $plain .= '\n';
                    elseif ($c2 == "r") $plain .= '\r';
                    elseif ($c2 == "t") $plain .= '\t';
                    elseif ($c2 == "b") $plain .= '\b';
                    elseif ($c2 == "f") $plain .= '\f';
                    elseif ($c2 >= '0' && $c2 <= '9') {
                        $oct = preg_replace("#[^0-9]#", "", substr($texts[$i], $j + 1, 3));
                        $j += strlen($oct) - 1;
                        $plain .= html_entity_decode("&#".octdec($oct).";");
                    }
                    $j++;
                break;

                default:
                    if ($isHex)
                        $hex .= $c;
                    if ($isPlain)
                        $plain .= $c;
                break;
            }
        }
        $document .= "\n";
    }

    return $document;
}


먼저 $document 변수를 만들어 놓네요. 맨 밑에 보니까 return 될 값이 들어갈 변수입니다.

즉 사람이 읽을 수 있는 완전한 데이터가 들어갈 변수죠.


다음은 $texts 의 count 만큼 for 문을 돌립니다.

그 for문 안에서 맨 먼저 하는 일은 4개의 변수를 정의해 놓는 거네요.

$isHex와 $isPlain 는 boolean 값이 들어갈 변수고 $hex와 $plain 은 어떤 문자 같은게 들어갈 변수인것 같습니다.


여기서 다시 for 문을 돌립니다. $texts 가 이중배열이라서 이렇게 작업하나 봅니다.

두번째 for 문에서는 $c 변수에 $texts[$i][$j] 를 담습니다.


그 다음에 switch 문이 나오는데... 처음에 < 와 > 를 체크하는 군요.


편의를 위해서 어제 봤던 데이터 중 일부를 아래 복사해 넣겠습니다.


(W)-36(e)7(e)7(k )46(o)7(f)
( )
(Oct)-11(o)5(ber )10(1)4( )
<00B2>
( )
(Oct)-11(o)5(ber )10(5)
( )
( )
( )
(Who)5(l)7(e)7( )-19(+ )-2(S)3(um)5( )
( )
( )
(Choice)
( )
(+)
( )
(F)20(lavor)


<00B2> 가 있네요. < 인 경우에는 $isHex 가 true 이고 > 인 경우에는 false 입니다.

그리고 > 인 경우에는 $hex 값을 array 로 바꿉니다.

str_split() 함수에서 그 일을 하죠.


<?php

$str 
"Hello Friend";

$arr1 str_split($str);
$arr2 str_split($str3);

print_r($arr1);
print_r($arr2);

?>


위 소스를 돌리면 아래 값을 얻습니다.

Array
(
    [0] => H
    [1] => e
    [2] => l
    [3] => l
    [4] => o
    [5] =>
    [6] => F
    [7] => r
    [8] => i
    [9] => e
    [10] => n
    [11] => d
)

Array
(
    [0] => Hel
    [1] => lo
    [2] => Fri
    [3] => end
)


어떤 일을 하는 함수인지 아시겠죠?

그 다음에는 $hexs 의 count 만큼  for 문을 돌립니다.

그 다음 그 각각의 값을 지난번에도 나왔던 str_pad() 함수를 사용해서 0을 4칸 붙이네요.


그 다음에 if 문에서 $transformations[$chex] 이 세팅돼 있으면 $chex 변수에 $transformations[$chex]을 대입합니다. 


그리고 나서 $document 에 값을 집어 넣는데요.

html_entity_decode() 함수를 사용합니다.


이 것은 html 을 string 으로 바꿔 주는 함수입니다.


<?php
$orig 
"I'll \"walk\" the <b>dog</b> now";

$a htmlentities($orig);

$b html_entity_decode($a);

echo 
$a// I'll &quot;walk&quot; the &lt;b&gt;dog&lt;/b&gt; now

echo $b// I'll "walk" the <b>dog</b> now
?>


위 예제를 보시면 어떤 일을 하는지 아시겠죠?


그러니까 <> 감싸여진 데이터는 hex 코드라서 이 case 문에서 그것을 처리하는 거네요.


그 다음 case 문에서는 (,) 를 체크합니다.


() 로 둘러싸인 부분은 그냥 text 죠. 사람이 읽을 수 있는..

그러니까 별다른 처리를 하지 않아도 되기 때문에 ) 인 경우에 $document 에 $plain 을 그냥 추가해 버리는 겁니다.


다음에는 \\ 를 체크하는데요.


우리가 다루는 pdf 파일에서는 이 값이 추출 되지 않았습니다.

어쨌든 내용을 보면 줄바꿈, 탭 뭐 이런 것들을 해당 sign 으로 바꿔서 $plain 에 넣는 일을 하네요. 숫자인 경우에는 거기에 맞게 또 처리를 하구요.


디폴트로는 $isHex 일 경우 $hex 에 $c를 추가하고 $isPlain 일 경우 $plain 에 $c를 추가합니다.


그리고 이렇게 만든 $document 를 이전 for 문에서 만든 $document 에 가를 하구요.

이렇게 for 문이 다 돌고 $document 에 값이 다 쌓였으면 이 값을 return 합니다.


그 return 값이 사람이 볼 수 있는 text 입니다.


이렇게 해서 얻은 결과는 아래와 같습니다.



잘 안 보이실 텐데요. 1번 글에서 업로드한 파일들을 다운 받아서 돌려 보시면 됩니다.


참고로 이 데이터를 가지고 요일별 메뉴를 display 하는 함수를 제가 만들어 봤는데요.



function menus($sources){
$resultlen  = strlen($sources);

$menuDate = substr($sources,0,48);
echo "<b><font size=6>Start Menu</font> <p><br> ". $menuDate. "<p></b>";


$result = preg_replace("/\s+/",'_',$sources);

$fs1 = strrpos($result,'_M_');

$menu1 = substr($result,$fs1,$resultlen);

$startTue = strpos($menu1,'_T_');
$startWed = strpos($menu1,'_W_');
$startThu = strrpos($menu1,'_T_');
$startFri = strpos($menu1,'_F_');
$endFri = strpos($menu1,'WEEKLY');

$Monday = str_replace('_', ' ' ,str_replace('_M_','Monday <br>',str_replace('FIT','FIT<br>',substr($menu1,0,$startTue))));
$Tuesday = str_replace('_', ' ' ,str_replace('_T_','Tuesday <br>',str_replace('FIT','FIT<br>',substr($menu1,$startTue,$startWed-$startTue))));
$Wednsday = str_replace('_', ' ' ,str_replace('_W_','Wednsday <br>',str_replace('FIT','FIT<br>',substr($menu1,$startWed,$startThu-$startWed))));
$Thuesday = str_replace('_', ' ' ,str_replace('_T_','Thusday <br>',str_replace('FIT','FIT<br>',substr($menu1,$startThu,$startFri-$startThu))));
$Friday = str_replace('_', ' ' ,str_replace('_F_','Friday <br>',str_replace('FIT','FIT<br>',substr($menu1,$startFri))));

echo "<table width=50%><tr><td>";

echo "<p> ". $Monday . "<p>";
echo "<p> ". $Tuesday . "<p>";
echo "<p> ". $Wednsday . "<p>";
echo "<p> ". $Thuesday . "<p>";
echo "<p> ". $Friday . "<p>";

echo "</td></tr></table><p><br><p> ";
}


그리고 함수 밖에서 이걸 부르면 되죠.

menus($result);

이렇게 하면 아래와 같은 결과가 나옵니다.




이렇게 해서 PDF 를 TEXT 로 변환하는 PHP 프로그램을 모두 분석해 봤습니다.

오랫만에 목욕해서 때를 싹 밀었을 때 처럼 개운하네요.


분석결과 위 소스는 제가 일하는데에서는 맞지 않아서 사용하지 않기로 했거든요.

그래서 저 결과도 깔끔하게 나온 것은 아닙니다.

참고하시구요.


다음에 또 소스 분석할 일 있으면 블로그에 정리해 놓을 께요.

이번 글은 기분 좋게 7번째 만에 마무리 했네요.





반응형