성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
Digital Stories
방명록
최근 덧글
[정성태] 그냥 RSS Reader 기능과 약간의 UI 편의성 때문에 사용...
[이종효] 오래된 소프트웨어는 보안 위협이 되기도 합니다. 혹시 어떤 기능...
[정성태] @Keystroke IEEE의 문서를 소개해 주시다니... +_...
[손민수 (Keystroke)] 괜히 듀얼채널 구성할 때 한번에 같은 제품 사라고 하는 것이 아...
[정성태] 전각(Full-width)/반각(Half-width) 기능을 토...
[정성태] Vector에 대한 내용은 없습니다. Vector가 닷넷 BCL...
[orion] 글 읽고 찾아보니 디자인 타임에는 InitializeCompon...
[orion] 연휴 전에 재현 프로젝트 올리자 생각해 놓고 여의치 않아서 못 ...
[정성태] 아래의 글에 정리했으니 참고하세요. C# - Typed D...
[정성태] 간단한 재현 프로젝트라도 있을까요? 저런 식으로 설명만 해...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
기타
생각의 전환
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 ad='csharp' style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>파판14 - 에오르제아의 시간 알람을 위한 C# WinForms 응용 프로그램</h1> <p> 오늘은 문득, 에오르제아의 시간이 현실 시간으로 어떻게 되나 궁금했습니다. 다행히, 이에 대한 힌트를 얻기 위해 검색해 본 다음의 사이트에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > http://ff14s.phps.kr/ </pre> <br /> 아래와 같은 <a target='tab' href='http://ff14s.phps.kr/ff14.js'>JavaScript 소스 코드</a>를 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > var mus = new Audio(); function get_et(){ var now = new Date(); <span style='color: blue; font-weight: bold'>var epock = Date.UTC(2010, 6, 12, 0, 0, 0) - 9 * 60 * 60 * 1000; return parseInt((parseInt((now.getTime() - epock) / 1000) - 90000) * (1440 / 70));</span> } function update_timezone_pos(){ var et = get_et(); <span style='color: blue; font-weight: bold'>var h = parseInt((et % (3600*24)) / 3600); var m = parseInt((et % 3600) / 60);</span> if(h==$("#h-set").val()&&m==$("#m-set").val()&&$("#h-set").val()!=""&&$("#m-set").val()!="") { mus.loop=true;mus.play(); if($("#ok-alarm").prop("checked")==true){setTimeout(function(){mus.pause();mus.currentTime=0;},5000);} } $("#eClock").text(("0"+h).substr(-2)+":"+("0"+m).substr(-2)); } $(function(){ $("#chk").click(function(){ $("#ifr").attr("src",""); }); $("#alarm-play").click(function(){ mus.src = "http://ff14s.dothome.co.kr/FFXIV.mp3"; mus.src = "https://a.clyp.it/ku4zi0bf.mp3"; mus.type = "audio/mpeg"; mus.preload="auto"; mus.loop=true; mus.play(); }); $("#alarm-stop").click(function(){ mus.pause(); mus.currentTime=0; }); update_timezone_pos(); setInterval(function(){ update_timezone_pos();},2500); }); </pre> <br /> 중요한 것은 get_et 함수인데요, 관련해서 JavaScript의 시간을 C#으로 변환하는 것에 대해 다음의 글을 참조하시면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > JavaScript와 C#의 시간 변환 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12849'>https://www.sysnet.pe.kr/2/0/12849</a> </pre> <br /> C#으로 현재의 에오르제아 시간 구하는 코드를 이렇게 구현할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static class TimeUtil { static DateTime _etCreated = new DateTime(2010, 6 + 1, 12, 0, 0, 0, DateTimeKind.Utc); static double _etEpoch = GetTime(_etCreated) - 9 * 60 * 60 * 1000; public static long GetTime(this DateTime time) { return (time.Ticks - 621355968000000000) / TimeSpan.TicksPerMillisecond; } public static double CurrentEorzeaTime { get { <span style='color: blue; font-weight: bold'>double time = ((GetTime(DateTime.UtcNow) - _etEpoch) / 1000 - 90000) * (1440.0 / 70); return time;</span> } } } </pre> <br /> 그리고 CurrentEorzeaTime으로부터 "시간"과 "분"을 최종적으로 다음과 같이 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > double now = TimeUtil.CurrentEorzeaTime; int hour = (int)((now % (3600 * 24)) / 3600.0); int minute = (int)((now % 3600) / 60.0); </pre> <br /> 자, 그럼 위에서 다뤘던 코드를 가만히 보면 에오르제아의 1분이 현실 시간으로 어떻게 되는지 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > double time = ((GetTime(DateTime.UtcNow) - _etEpoch) / 1000 - 90000) * <span style='color: blue; font-weight: bold'>(1440.0 / 70)</span>; </pre> <br /> 우선 아래의 코드는 "- 90000"을 제외하면 그냥 epoch 시간으로부터 흐른 총 초를 의미합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ((GetTime(DateTime.UtcNow) - _etEpoch) / 1000 - 90000) </pre> <br /> 그리고 그 초에 (1440.0 / 70의 결과인) 20.571428...로 571428이 반복되는 순환소수를 곱합니다. 즉, 현실 시간의 1초가 흐르면 에오르제아 세계에서는 20.571428... 초가 흐르는 것입니다.<br /> <br /> 에오르제아는 시간을 "hh:mm"으로 보여주는데 결국 현실 시간으로 3초가 안 되는 시간이 흐르면 에오르제아에서는 1분이 흐르는 것입니다. 달리 말해 에오르제아의 1분은 아래의 비례식을 풀어,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 1:20.571428... = x:60 (1440/70) * x = 60 x = 60 / (1440/70) x = 2.916...(6 순환)... </pre> <br /> 현실에서 2.916... 초의 딱 떨어지지 않는 시간이 흘렀을 때 에오르제아에서는 1분이 지나 버리는 것입니다. (아마도, 에오르제아라는 행성은 지구보다 중력 가속도가 엄청 작아 시간이 빠르게 흐르는 듯합니다.)<br /> <br /> 이것을 따져봤을 때, ff14.js에 있는 소스 코드에서 setInterval 함수가,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > setInterval(function(){ update_timezone_pos();},<span style='color: blue; font-weight: bold'>2500</span>); </pre> <br /> 2500의 값을 쓰는 것이 그리 좋은 생각은 아닙니다. 하지만 이게 무슨 우주 왕복선의 코드도 아니니... ^^ 충분히 용납될 수 있습니다.<br /> <br /> 어쨌든, 저런 식의 계산으로 인해 현실 시간의 70분마다 에오르제아에서는 24시간의 하루가 지나게 됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그건 그렇고, 자바스크립트의 코드를 보면 좀 이해가 안 되는 부분이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > function get_et(){ var now = new Date(); var epock = Date.UTC(2010, 6, 12, 0, 0, 0)<span style='color: blue; font-weight: bold'> - 9 * 60 * 60 * 1000</span>; return parseInt((parseInt((now.getTime() - epock) / 1000) - 90000) * (1440 / 70)); } </pre> <br /> 9 * 60 * 60 * 1000은 9시간에 대한 총 밀리 초를 의미합니다. 그런데 왜 굳이 UTC에서 9시간을 뺸 것일까요? 게임 서버가 위치한 곳이 한국이라고 가정했을 때 한국 표준시(KST)에 해당하는 9시간을 빼면 UTC가 나옵니다. 즉, 위의 코드는 어차피 Local Time이 아닌 UTC 시간에서 다시 KST 시간에 해당하는 밀리 초만큼을 빼고 있는 것입니다.<br /> <br /> 저 오류는 아마도 파판14 측의 개발자에서부터 잘못한 것으로 보입니다. 어쩌면 그는 UTC/Local 시간에 대한 정확한 이해가 없는 상태에서 저렇게 시간을 정한 듯싶고 이후 그 계산법에서 파생된 여러 소스 코드들에서 어쩔 수 없이 (UTC - 9시간)에 해당하는 수식을 넣어야만 했을 것입니다.<br /> <br /> 마지막으로, 저렇게 만든 시간이 정작 게임에서 보이는 시간과는 ET 1~2(초가 아닌)분의 차이가 발생할 수 있습니다. 왜냐하면 <a target='tab' href='https://www.sysnet.pe.kr/2/0/11883'>해당 게임 서버의 시간과 여러분의 컴퓨터 시간이 정확히 일치하지는 않을 것</a>이기 때문에 그 정도 차이는 가능합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자... 시간에 대한 이야기는 이걸로 끝이고, 이제 남은 작업은 약간 지루한 것들입니다. 사용자가 원하는 시간을 설정할 수 있도록 해야 하고, 그 값을 저장 및 복원하는 것도 필요할 것입니다. 또한 당연히 설정한 시간과 분이 되었을 때 알릴 수 있어야 하고.<br /> <br /> 그중에서, 사용자에게 알리는 부분은 다음의 코드를 넣으면 좋을 듯합니다.^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > .NET 코드 - 창 흔드는 효과 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/966'>https://www.sysnet.pe.kr/2/0/966</a> </pre> <br /> 그리고 이 모든 것을 종합해 Windows Forms 응용 프로그램을,<br /> <br /> <img alt='ff14_alarm_timer_winform_1.png' src='/SysWebRes/bbs/ff14_alarm_timer_winform_1.png' /><br /> <br /> 만든 <a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1871&boardid=635954948'>소스 코드를 첨부</a>했으니 원하시는 분은 가져다 써도 되겠습니다. ^^<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1550
(왼쪽의 숫자를 입력해야 합니다.)