messier - 현재 관측 가능한 메시에 천체(실시간 지평선 위) PHP/8.0.22

... Loading ...

소스닫기 | 24절기 계산 | 음양력변환, 일출몰, 월출몰, 별자리, 일월식 계산 | 메시에 관측정보(실시간) | 메시에 관측정보(오늘전체) | deltaT 계산 | 부활절 날짜 계산
<?php
##
function mrskey($JD0$moonrsJD$sunrJD$sunsJD$twrJD$twsJD)
{
  if(
$moonrsJD $sunsJD) return 0;
  if(
$moonrsJD $twsJD)  return 2;
  if(
$moonrsJD $JD0)    return 4;
  if(
$moonrsJD $twrJD)  return 6;
  if(
$moonrsJD $sunrJD) return 8;

  return 
10;
}

function 
moon_pos_simple($JD$loc$yet_pos='-')
{
  list(
$malt,$mpos) = moon_pos($JD,$loc);

  
// yet rise, 8/60 == moon_zenith
  
if($malt < (8/60)) { $mposp '-'$mpos $yet_pos; }
  else 
$mposp $mpos.round($malt);

  return array(
$mposp,$mpos);
}

function 
moon_today_yesterday($JD0$JD12$rs_today$rs_yesterday)
{
  
$rsp  '';
  [ 
$todayJD    $todayhm     ] = $rs_today;
  [ 
$yesterdayJD$yesterdayhm ] = $rs_yesterday;

  if(
$todayJD && $todayJD<$JD12)  // JD12 is today 12:00(last point)
  
{
    
$rs   $todayhm;
    
$rsJD $todayJD;
  }
  else if(
$yesterdayJD && $yesterdayJD>($JD12-1))  // yesterday 12:00
  
{
    
$rsp  '-';
    
$rs   $yesterdayhm;
    
$rsJD $yesterdayJD;
  }
  else
  {
    if(isset(
$rs_today[3]) && $rs_today[3]>($JD12-1))
    {
        
$rsp  '-';
        
$rs   calendar::jd2hm($rs_today[3]);  // 어제 뜨거나 지는 시간
        
$rsJD $rs_today[3];
    }
    else if(isset(
$rs_yesterday[3]) && $rs_yesterday[3]>$JD0)
    {
        
$rs   calendar::jd2hm($rs_yesterday[3]);  // 어제 날짜 기준으로 오늘 뜨거나 지는 시간
        
$rsJD $rs_yesterday[3];
    }
    else
    {
        
$rs   $todayhm;
        
$rsJD $todayJD;
    }
  }

  return array(
$rsp,$rs,$rsJD);
}

function 
moon_today_tomorrow($JD0$JD12$rs_today$rs_tomorrow)
{
  
$rsp  '';
  [ 
$todayJD   $todayhm    ] = $rs_today;
  [ 
$tomorrowJD$tomorrowhm ] = $rs_tomorrow;

  if(
$todayJD && $todayJD>$JD12)  // JD12 is today 12:00(first point)
  
{
    
$rs   $todayhm;
    
$rsJD $todayJD;
  }
  else if(
$tomorrowJD && $tomorrowJD<($JD12+1))
  {
    
$rsp  '+';
    
$rs   $tomorrowhm;
    
$rsJD $tomorrowJD;
  }
  else
  {
    if(isset(
$rs_today[3]) && $rs_today[3]<($JD12+1))
    {
        
$rsp  '+';
        
$rs   calendar::jd2hm($rs_today[3]);  // 내일 뜨거나 지는 시간
        
$rsJD $rs_today[3];
    }
    else if(isset(
$rs_tomorrow[3]) && $rs_tomorrow[3]<$JD0)
    {
        
$rs   calendar::jd2hm($rs_tomorrow[3]);  // 어제 날짜 기준으로 오늘 뜨거나 지는 시간
        
$rsJD $rs_tomorrow[3];
    }
    else
    {
        
$rs   $todayhm;
        
$rsJD $todayJD;
    }
  }

  return array(
$rsp,$rs,$rsJD);
}

//if(preg_match('/gzip/',$_SERVER['HTTP_ACCEPT_ENCODING']) && !headers_sent()) @ini_set('zlib.output_compression','On');

require_once '_lib/class.calendar.php';
require_once 
'_lib/class.astro.php';
require_once 
'_lib/class.meeus.php';
require_once 
'_lib/class.de405.php';
require_once 
'_lib/class.stellar.php';
require_once 
'_lib/func.array.php';
require_once 
'_lib/func.debug.php';

DE405::set_datadir($_SERVER['DOCUMENT_ROOT'].'/_lib');

## rstime/footer.php
$_js_utils_php 1;
$_js_jquery_min_php 1;
$_js_jquery_tablesorter_min_php 1;
$_js_jquery_metadata_php 1;

$_uri  $_SERVER['REQUEST_URI'];
$_self $_SERVER['SCRIPT_NAME']; //basename($_SERVER['SCRIPT_NAME']);
$_baseurl $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/';  // for erro path_info/img...
$_tablewidth 820// px
$_datetime '';
$title 'messier - 현재 관측 가능한 메시에 천체(실시간 지평선 위)';

if(isset(
$_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'])
{
  
$_datetime str_replace('/','',$_SERVER['PATH_INFO']);
  list(
$_date,$_time) = explode('.',$_datetime);

  
$_d substr($_date,-2);
  
$_m substr($_date,-4,2);
  
$_y preg_replace("/${_m}${_d}$/",'',$_date);
  
$_h substr($_time,0,2);
  
$_i substr($_time,2,2);
}

## locations
##
$_locs astro::location_kr(NULL);
$seluloc $seldloc = array('','');
$loc  = array();
$uidx $didx 0;
$uloc $_COOKIE['uloc'] ?? '';

if(
$uloc)
{
  list(
$sidx,$uloc) = explode('|',trim(urldecode($uloc)));
  if(
$sidx 100)
  {
    if(isset(
$_locs[$sidx]))
    {
        
$didx $sidx;
        
$loc  $_locs[$sidx];
    }
  } else
  {
    list(
$ulon,$ulat) = explode(',',$uloc);
    
$loc[0] = $ulondeg astro::minmax(astro::dms2deg($ulon,2),-180,180);
    
$loc[1] = $ulatdeg astro::minmax(astro::dms2deg($ulat,2),-57,57);
    
$loc[2] = '사용자입력';
    
$uidx 1;
  }
}
else 
$loc $_locs[0];

$seluloc[$uidx] = 'CHECKED';
$seldloc[$didx] = 'SELECTED';

$_locsp '';
foreach(
$_locs AS $k=>$arr)
{
  
$_locsp .= "<option value='$k' ".($seldloc[$k] ?? '').">$arr[0]$arr[1] ($arr[2])</option>\n";
}

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE><?=$title?></TITLE>
<base href="<?=$_baseurl?>" /> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript">
<!--
var starttime = (new Date()).getTime();
//-->
</SCRIPT>
<STYLE TYPE="text/css">
<!--
  * { font-family:NanumGothic,'나눔고딕','Malgun Gothic',Dotum,'돋움',Gulim,'굴림',Helvetica,Apple-Gothic; }
  body { font-size:10pt; /* background: url(/images/_N8D20.jpg) no-repeat 100% 0% fixed; */ }
  td { font-size:9pt; vertical-align:middle; }

  th.header { background-image: url(/images/sort.default4.gif);
    background-repeat:no-repeat;
    background-position:100% 50%;
    cursor:pointer;
    border:1px solid #cccccc;
    padding-left:2px; /* 1px */
    padding-right:2px; } /* 5px */
  th.headerSortUp { background-image: url(/images/sort.desc4.gif);
    background-repeat:no-repeat; color:#ff00ff; }
  th.headerSortDown { background-image: url(/images/sort.asc4.gif);
    background-repeat:no-repeat; color:#ff00ff; }

  .ttcl, .tbcl, .tim { font-size:8pt; text-align:center; border-collapse:collapse; width:<?=$_tablewidth?>px; }
  .tbcl td, .tbclt td { border:1px solid #cccccc; vertical-align:middle; height:30px; }
  .thcl { font-weight:bold; height:40px; /* background-color:#cccccc; */ }
  .tbclt { font-size:8pt; text-align:center; border-collapse:collapse; width:<?=$_tablewidth?>px; }
  .ttcl td, .tim td { border:1px solid #cccccc; vertical-align:middle; height:30px; }
  .tim td { text-align:center; font-size:8pt; }

  /* .tset td { height:30px; border:1px solid #cccccc; } */
  .tset {
    display: table-cell; vertical-align: middle; 
    padding: 10px;
    margin: 10px 5px 20px 5px;  /* 상, 우, 하, 좌 */ /* 바깥쪽 여백임 */
    background-color:#eeeeee; border-radius:0.5em/0.5em; }

  .warn { border: 1px solid #ff0000; }
  .smallfont { font-size:8pt; } /** TR **/
  .vtfcolor { color:#333366; }  /** TR **/
  .grey { background-color:#aaaaaa; }
  .dark, .good, .best {  background-color:#000000; color:#cccccc; }
  .better { background-color:#330000; color:#cccccc; }
  .some { background-color:#993300; }
  .bad { color:#ffffff; background-color:#990099; }
  .todaymark { background-color:#eeeeee; }

  .tohide { color:#ffffff; font-size:0em; }
  .pointer { cursor:pointer; }
  .comment { color:#666699;
    font-size:11px;
    font-weight:normal;
    /* padding-left:0.1em; */
    background-color:#eeeeee;
    border-radius:0.5em/0.5em;
    width:800px;
    display: table-cell; vertical-align: middle; 
    padding: 10px;
    margin: 10px 5px 20px 5px;  /* 상, 우, 하, 좌 */ /* 바깥쪽 여백임 */
    background-color:#eeeeee; border-radius:0.5em/0.5em; }

  input, select { font-size:9pt; background-color:#ffffff; border:solid 1px #4f7292; margin:0 0 0 0; height:30px; }

  /*
  .margenta { color:#ff00ff; }
  .markwarn { color:#ffffff; background-color:#990099; }
  */

  .bold { font-weight:bold; }
  .easy { font-weight:bold; } /* background-color:#ffcc00 */
  .normal { font-weight:bold; } /* background-color:#006600 */
  .difficult { font-weight:bold; color:#999999; } /* background-color:#cc0000 */
  .challenge { font-weight:bold; color:#999999; } /* background-color:#990099 */
  .notfind, .notview { font-weight:bold; color:#999999; } /* background-color:#000000 */

  .pagewait { position:absolute; text-align:center; vertical-align:middle;
    width:400; height:200; border:0; background-color:transparent;
    left:200; top:185; color:#0000ff; }

  .vmiddle { vertical-align:middle; }

  #box { position:absolute;
    width:380px; height:250px; text-align:center; vertical-align:middle;
    margin:0px; padding:0px;
    left:200; top:100;
    border:1px solid #4f7292; font-family:Tahoma; font-size:11px; background-color:#ffffff; }
  #box td { font-size:11px; }
  #box input { margin:3px 0 3; }  /* 상, 우, 하, 좌 */ /* 바깥쪽 여백임 */
  span#box:hover { text-decoration:underline; }

  #boxclose { cursor:pointer; text-align:right; padding-right:15px; padding-top:8px; color:#0000ff; }

  #setloc, .totop, .showhide { cursor:pointer; font-size:11px; color:#0000ff; text-decoration:underline; }
  .tbloc { font-size:8pt; border-collapse:collapse; margin:0px auto; }  /* table center align to margin:0px auto */
  .tbloc td { border:1px solid #cccccc; vertical-align:middle; height:50px; }
  .radio { border:0; vertical-align:middle; }
  .toactive { cursor:pointer; }
  #errmsg { color:#ff0000; }
  .viewlimg { cursor:pointer; }
  #viewlimg { position:absolute; text-align:center; vertical-align:middle;
    left:150; width:750; height:800; border:0; }

  .code {
    /* display: block | table-cell | inline-table; */
    display: table-cell; vertical-align: middle; 
    padding: 10px;
    margin: 10px 5px 20px 5px;  /* 상, 우, 하, 좌 */ /* 바깥쪽 여백임 */
    background: #eeeeee;
    border-radius: 0.5em / 0.5em;
    font-family: Dotumche,monospace; white-space: pre;
    width:800px; }
  .pre-fontspace  { font-family:Dotumche,Helvetica,monospace; white-space: pre; }
  .pre-font  { font-family:Dotumche,Helvetica,monospace; }
  .pre-space { white-space: pre; }
  .solidbox {
    display: table-cell; vertical-align: middle;
    padding: 10px;
    margin: 10px 5px 20px 5px;  /* 상, 우, 하, 좌 */ /* 바깥쪽 여백임 */
    background: #eeeeee;
    border-radius: 0.5em / 0.5em; } /* 모서리 둥글게 */

  .thin-line           { border-top: 1px solid #ddd; margin: 0px 0px; }
  .tabs                { display: inline-block; width: <?=$_tablewidth?>px; margin: 0 auto; }
  .tabs .menu          { background: none; width: 57px; text-align: center; color: #111; display: inline-block; padding: 15px 10px; cursor: pointer; }
  .tabs .menu:hover    { background: #eee; }
  .tabs .menu.current  { background: #eee; font-weight: bold; } /* border-radius:  0.5em / 0.5em; */
  .tab-content         { display: none; padding: 0px; }
  .tab-content.current { display: inherit; }
  .tabchanger:hover    { background: #eee; }
//-->
</STYLE>
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript" SRC='/_lib/js.utils.php'></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript" SRC='/_lib/js.jquery.min.php'></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript" SRC='/_lib/js.jquery.tablesorter.min.php'></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript" SRC='/_lib/js.jquery.metadata.php'></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" type="text/JavaScript">
<!--
function enable_sortable(tid)
{
  var trnum = $('#'+tid+' tbody > tr').length;
  if(trnum < 2) return;

  $("#"+tid).tablesorter
  ({
    headers:
    {
        0: { sorter: "toint" },
        1: { sorter: "text" },
        2: { sorter: "numberic" },
        3: { sorter: "text" },
        4: { sorter: "text" },
        5: { sorter: "numberic" },
        6: { sorter: "text" },
        7: { sorter: "text" },
        8: { sorter: "text" },
        9: { sorter: "text" },
        10:{ sorter: "text" }
    },
    sortMultiSortKey: 'altKey'
  });

  return;
}

function echo(s)
{
  document.write(s);
}

function mkjd(y, m, d, h, i, s)
{
  var a, b, jc, JD;

  if(m < 3) { m += 12; y -= 1; }

  jc = (y*10000.0) + (m*100.0) + d;
  d = d + (h/24.0) + (i/1440.0) + (s/86400.0);
  a = Math.floor(y/100);
  b = (jc < 15821015) ? 0 : (2.0 - a + Math.floor(a/4.0));
  JD = Math.floor(365.25*(y+4716.0)) + Math.floor(30.6001*(m+1.0)) + d + b - 1524.5; // error

  return JD;
}

function days_in_month(y, m)
{
  var n;
  var months = new Array(31,0,31,30,31,30,31,31,30,31,30,31);

  //if(y+''+m == 158210) return 21; // 1582-10-01 ~ 31 == 21 days

  n = months[(m-1)];
  n = n ? n : (isleap(y) ? 29 : 28);

  return n; // integer
}

function isleap(y)
{
  if(y < 1582) return (y%4) ? false : true; // for julian calendar

  // for gregorian calendar
  if(y % 4) return false;
  else if(y % 100) return true;
  else if(y % 400) return false;

  return true; // else 400*Y
}

function dms2deg(dms)
{
  dms = dms.replace(/[^\d.+-]+/g,' ',dms);
  dms = dms.replace(/^\s+/,'').replace(/\s+$/,''); // trim()
  var d = dms.split(' '); // Array

  if(!d[0]) d[0] = 0;
  if(!d[1]) d[1] = 0;
  if(!d[2]) d[2] = 0;

  if(d[0].match(/^-/)) var deg = Number(d[0]) - Number(d[1]/60) - Number(d[2]/3600);
  else var deg = Number(d[0]) + Number(d[1]/60) + Number(d[2]/3600);

  deg = Math.round(deg*100) / 100;

  return deg;
}

function days_back()
{
  var n;
  var y = Number($('#_y').val());
  var m = Number($('#_m').val());
  var d = Number($('#_d').val());

  d--;

  if(d < 1)
  {
    m--;
    if(m < 1)
    {
        m = 12;
        y--;
        $('#_y').val(y);
    }
    if(m < 10) m = '0' + m;
    $('#_m').val(m);
    d = days_in_month(y,m);
  }

  if(d < 10) d = '0' + d;
  $('#_d').val(d);

  return;
}

function days_forward()
{
  var n;
  var y = Number($('#_y').val());
  var m = Number($('#_m').val());
  var d = Number($('#_d').val());

  d++;

  n = days_in_month(y,m);

  if(d > n) // next month
  {
    d = 1;
    m++;
    if(m > 12)
    {
        m = 1;
        y++;
        $('#_y').val(y);
    }
    if(m < 10) m = '0' + m;
    $('#_m').val(m);
  }

  if(d < 10) d = '0' + d;
  $('#_d').val(d);

  return;
}

function hours_back()
{
  var h = Number($('#_h').val());

  h--;

  if(h < 0)
  {
    h = 23;
    days_back();
  }

  if(h < 10) h = '0' + h;

  $('#_h').val(h);

  return;
}

function hours_forward()
{
  var h = Number($('#_h').val());

  h++;

  if(h > 23)
  {
    h = 0;
    days_forward();
  }

  if(h < 10) h = '0' + h;

  $('#_h').val(h);

  return;
}

function focus2end(id)
{
  $(id).focus();
  $(id).val($(id).val()+''); // focus end

  return;
}

function zerofill(str, cnt)
{
  str = '0000000000'+str;
  return str.substr(str.length-cnt, cnt);
}

$(window).bind('load',function()
{
  $('img').each(function()
  {
    if((typeof this.naturalWidth != "undefined" && this.naturalWidth == 0 ) || this.readyState == 'uninitialized')
    {
        //$(this).attr('src', '/images/n.gif');
        this.src = '/images/n.gif';
        this.border = 1;
        this.width = 28;
        this.height = 30;
        this.alt = 'no image';
    }
  });
});

$(document).ready(function()
{
  $.tablesorter.addParser
  ({
    id: "toint",
    is: function(s)
    {
        return true;
    },
    format: function(s)
    {
        s = s.replace(/[^\d]+/,'');
        if(s == '') s = 100;
        return s;
    },
    type: "numeric"
  });

  enable_sortable('tsortNW');
  enable_sortable('tsortW');
  enable_sortable('tsortSW');
  enable_sortable('tsortS');
  enable_sortable('tsortSE');
  enable_sortable('tsortE');
  enable_sortable('tsortNE');
  enable_sortable('tsortN');
  enable_sortable('tsortyet');

  $('#setto').click(function()
  {
    var date = $('#_y').val() + $('#_m').val() + $('#_d').val();
    var time = $('#_h').val() + $('#_i').val();

    var datetime = date + '.' + time;

    var ruri = location.href.replace(/\.php.+$/,'.php');
    location.href = ruri + '/' + datetime;
    //window.location = ruri + '/' + datetime;

    return false;
  });

  $('#currto').click(function()
  {
    location.href =    location.href.replace(/\.php.+$/,'.php');
    return false;
  });

  var boxshow = 0;
  $('#setloc, #boxclose').click(function()
  {
    if(boxshow) $('#box').hide();
    else $('#box').show();

    boxshow ^= 1;
    return;
  });

  $('#dback').click(function()
  {
    days_back();
    return;
  });

  $('#dforward').click(function()
  {
    days_forward();
    return;
  });

  $('#hback').click(function()
  {
    hours_back();
    return;
  });

  $('#hforward').click(function()
  {
    hours_forward();
    return;
  });

  var showhides = new Array();

  $('.showhide').click(function()
  {
    var tid = this.id.replace(/close$/,'');

    if(!showhides[tid])
    {
        $('#'+tid).hide();
        $('#'+tid+'close').html('&laquo;보기');
    } else
    {
        $('#'+tid).show();
        $('#'+tid+'close').html('&laquo;감추기');
    }

    showhides[tid] ^= 1;
    return;
  });

  $('.totop').click(function()
  {
    window.scrollTo(0,0);
    return;
  });

  $('#saveuloc').click(function()
  {
    var loc = v = p = '';
    var t = $(':input:radio[name=radiouloc]:checked').val();

    if(t == 1)
    {
        var warnclass = $('#ulon').attr('class') + $('#ulat').attr('class');
        if(warnclass.match(/warn/)) return false;

        var lon = $('#ulon').val();
        var lat = $('#ulat').val();
        v = 101 + '|' + lon + ',' + lat;
        p = dms2deg(lon) + ', ' + dms2deg(lat) + ' (사용자입력)';
    } else
    {
        var idx = $("#ploc option:selected").val();
        var txt = $("#ploc option:selected").text();
        v = idx + '|' + txt;
        p = txt;
    }

    $('#loc').text(p);
    //setcookie('uloc',encodeURI(v)); // save cookie
    setcookie('uloc',encodeURI(v),365); // save cookie
    //$('#errmsg').html('<font color=blue>OK</font>');

    $('#box').hide();
    boxshow = 0;

    return;
  });

  $('.toactive, .radio').click(function()
  {
    var tofocus = 0;
    var v = '';
    var idn = this.id.replace(/(to|uloc)/,'');

    //$(':input:radio[name=radiouloc]').filter('input[value='+idn+']').attr("checked", "checked"); // ok
    $('#uloc'+idn).attr("checked", "checked");

    if(idn > 0)
    {
        v = $('#ulon').val();
        if(v.length>0 && v.match(/^[\d\s+-.'"dms]+$/))
        {
            $('#ulon').removeClass('warn');
            $('#ulondeg').text(dms2deg(v));
        } else
        {
            $('#ulon').addClass('warn');
            focus2end('#ulon');
            tofocus = 1;
        }

        v = $('#ulat').val();
        if(v.length>0 && v.match(/^[\d\s+-.'"dms]+$/))
        {
            $('#ulat').removeClass('warn');
            $('#ulatdeg').text(dms2deg(v));
        } else
        {
            $('#ulat').addClass('warn');
            if(!tofocus) focus2end('#ulat');
        }
    } else
    {
        $('#ulon, #ulat').removeClass('warn');
        $('#errmsg').text('');
    }

    return;
  });

  $('#ulon, #ulat').bind("keydown keyup click focus blur",function(e)
  {
    var errmsg = '';
    $('#uloc1').attr("checked", "checked");

    var v = $('#ulon').val();
    if(v.length>0 && v.match(/^[\d\s+-.'"dms]+$/))
    {
        $('#ulon').removeClass('warn');
        if(this.id == 'ulon') $('#ulondeg').text(dms2deg(v));
    } else
    {
        $('#ulon').addClass('warn');
        if(v.length > 0) errmsg = '경도';
    }

    var v = $('#ulat').val();
    if(v.length && v.match(/^[\d\s+-.'"dms]+$/))
    {
        $('#ulat').removeClass('warn');
        if(this.id == 'ulat') $('#ulatdeg').text(dms2deg(v));
    } else
    {
        $('#ulat').addClass('warn');
        if(v.length > 0) errmsg += ' 위도';
    }

    if(errmsg) errmsg = errmsg.replace(/^\s+/,'') + ' 입력 에러';
    $('#errmsg').text(errmsg);

    return;
  });

  $('#viewlimg').click(function()
  {
    $('#viewlimg').hide();
    //alert(this.src);
  });

  $('.viewlimg').click(function()
  {
    var imgsrc = $(this).attr('SRC').replace(/-s\.gif/,'.jpg');

    if(imgsrc.match(/n\.gif$/)) return false;

    if(imgsrc.match(/G[\d]+\.jpg$/))
    {
        imgsrc = imgsrc.replace(/G([\d]+\.jpg)/,"NGC$1");
        //alert(imgsrc);
    }

    var cpos = $(window).scrollTop() + 10; // current scroll position
    $('#viewlimg').css('top',cpos);
    $('#viewlimg').html('<img src='+imgsrc+' border=0 alt="click to close">');
    $('#viewlimg').fadeIn(1500);
    return;
  });

  $('#_m').change(function()
  {
     var i;
    var y = Number($('#_y').val());  // 현재 선택된 년도
    var m = Number($('#_m').val());
    var d = Number($('#_d').val());
    var dms = days_in_month(y,m);
    var newhtml = "";
    var viewday
    for(i=1; i<=dms; i++)
    {
        viewday = zerofill(i,2);
        newhtml += "<option value="+i+">"+viewday+"일</option>"
    }
    // Replace all the options with new options
    $("#_d").html(newhtml);
    $("#_d").val(d).attr("selected","selected");

    return;
  });

  $('.tabs .menu, .tabchanger').click(function()
  {
    var tabidx = $(this).attr('tabidx');

    $('.tabs .menu').removeClass('current');
    $('.tab-content').removeClass('current');

    //$(this).addClass('current');  // ok work
    $('#tabmenu-'+tabidx).addClass('current');
    $('#'+tabidx).addClass('current');
  });

  $('#pagewait').hide(); // last
});
//-->
</SCRIPT>
</HEAD>
<BODY>
<H2><?=$title.' PHP/'.PHP_VERSION?></H2>
<div id='pagewait' class='pagewait'><H1>... Loading ...</H1></div>
<div id='box' style='display:none'>
<div align=right id=boxclose>[close]</div>
<br>
관측지 설정/변경하기
<table width=97% class=tbloc>
<form name=ploc>
<tr><td valign=middle width=80><input type=radio name=radiouloc class=radio id=uloc0 value=0 <?=$seluloc[0]?>>
<span class=toactive id=to0>기본값</span></td>
<td><select id=ploc><?=$_locsp?></select></td></tr>
<tr style='height:80px'><td valign=middle>
<input type=radio name=radiouloc class=radio value=1 id=uloc1 <?=$seluloc[1]?>>
<span class=toactive id=to1>직접입력</span>
</td><td>
<input type=text value='<?=$ulondeg??''?>' id=ulon> 경도 <span id=ulondeg><?=$ulondeg??''?></span><br>
<input type=text value='<?=$ulatdeg??''?>' id=ulat> 위도 <span id=ulatdeg><?=$ulatdeg??''?></span> (-57 ~ +57)
</td></tr>
<tr><td colspan=2 align=center><input type=button id=saveuloc value=' 저장(Cookie) '><br><span id=errmsg>&nbsp;</span></td></tr>
</form>
</table>
</div>
<div id='viewlimg' style='display:none'></div>
<?php
$_menuindex 
= array
(
  
'solar.php'         => '24절기 계산',
  
'lunar.php'         => '음양력변환, 일출몰, 월출몰, 별자리, 일월식 계산',
  
'messier.php'       => '메시에 관측정보(실시간)',
  
'messier.today.php' => '메시에 관측정보(오늘전체)',
  
'deltat.php'        => 'deltaT 계산',
  
'easter.php'        => '부활절 날짜 계산'
);

$menu '';
foreach(
$_menuindex AS $k=>$v)  $menu .= " | <A HREF='$k'>$v</A>";

if(isset(
$_GET['view']))
{
  echo 
'<A HREF="'.$_self.'">소스닫기</A>'.$menu.'<HR>'."\n";
  
highlight_file(basename($_self));
  return;
}

echo 
'<A HREF="'.$_self.'?view=1">소스보기</A>'.$menu.'<HR>'."\n";
echo 
"<H2>데모 - 현재 어떤 천체를 볼 수 있는지(방향별) ...</H2>\n";

## date time and location
##
if($_datetime$JD calendar::getjd($_y,$_m,$_d,$_h,$_i,0); // JD or input UTC time
else list($JD,$_y,$_m,$_d,$_h,$_i) = calendar::curr_datetime();

$_i floor($_i/5) * 5// rewrite

## polaris
##
list(,,$polar,$polarr) = stellar::polaris_pos($JD,$loc);
$polar  '<span class=smallfont>'.astro::h2hm30($polar).'</span>';
$polarr '<span class=smallfont>'.astro::h2hm30($polarr).'</span>';

## sun rise/set/tw
##
$sunriseset, , , $twriseset ] = sun_riseset($JD,$loc);  // all
[ [$sunrJD,$sunr], [$sunsJD,$suns] ] = $sunriseset;
[ [
$twrJD ,$twr ], [$twsJD ,$tws ] ] = $twriseset;

## moon rise/set
##
[ [$moonrise_today,$moonset_today], $mcult ] = moon_riseset($JD,$loc);
$mcul $mcult[0] ? ($mcult[1].'('.$mcult[3].round($mcult[2]).')') : '';

$mrp  $msp '';
$JD0  calendar::jd2jd0($JD);
$JD12 $JD0 0.5;

## 이전 날 저녁 + 당일 새벽
##
if($_h 7)
{
  
$printw[0]    = '이전 날('.  calendar::date('m/d,l',$JD-1).')';
  
$printw[1]    = '관측 당일('.calendar::date('m/d,l',$JD).')';
  
$todaymark[1] = 'class=todaymark';

  [ 
$sunriseset, , , $twriseset ] = sun_riseset($JD-1,$loc);  // all
  
[ [$moonrise_yesterday,$moonset_yesterday], $mcul_yesterday ] = moon_riseset($JD-1,$loc);
  [ ,[
$sunsJD,$suns] ] = $sunriseset;
  [ ,[
$twsJD ,$tws ] ] = $twriseset;

  if(!
$mcul$mcul '-'.$mcul_yesterday[1].'('.$mcul_yesterday[3].round($mcul_yesterday[2]).')';
  list(
$mrp,$mrise,$mriseJD) = moon_today_yesterday($JD0,$JD12,$moonrise_today,$moonrise_yesterday);  // moon rise
  
list($msp,$mset ,$msetJD)  = moon_today_yesterday($JD0,$JD12,$moonset_today ,$moonset_yesterday);   // moon set
}

## 당일 저녁 + 다음 날 새벽
##
else
{
  
$printw[0]    = '관측 당일('.calendar::date('m/d, l',$JD).')';
  
$printw[1]    = '다음 날('.  calendar::date('m/d, l',$JD+1).')';
  
$todaymark[0] = 'class=todaymark';
  
$JD0 += 1;

  [ 
$sunriseset, , , $twriseset ] = sun_riseset($JD+1,$loc);  // all
  
[ [$moonrise_tomorrow,$moonset_tomorrow], $mcul_tomorrow ] = moon_riseset($JD+1,$loc);
  [ [
$sunrJD,$sunr] ] = $sunriseset;
  [ [
$twrJD ,$twr ] ] = $twriseset;

  if(!
$mcul$mcul '-'.$mcul_tomorrow[1].'('.$mcul_tomorrow[3].round($mcul_tomorrow[2]).')';
  list(
$mrp,$mrise,$mriseJD) = moon_today_tomorrow($JD0,$JD12,$moonrise_today,$moonrise_tomorrow);
  list(
$msp,$mset ,$msetJD)  = moon_today_tomorrow($JD0,$JD12,$moonset_today ,$moonset_tomorrow);
}

## 월령 계산(local 0시기준)
##
$lunar    tolunar($JD0);
$moonage  $JD0 $lunar[2][2];
$moonage  = ($moonage<0) ? 30.0 sprintf('%.1f',$moonage);
$moonagep = (int)$moonage;

## dark time
##
$dark   = ($twrJD $twsJD) * 24// total dark hour times
$darkh  astro::h2hm($dark);
$moon_visible = (int)(($msetJD $twsJD) || ($mriseJD $twsJD));
$mdark  = ($mriseJD $twsJD) ? max($twrJD-$msetJD,0) : (min($mriseJD,$twrJD) - $twsJD);
$mdark *= 24;  // to hours

## initial of group sun/moon rise/set
##
$vtm[1] = array($suns  ,'일몰');
$vtm[3] = array($tws   ,'천문박명');
$vtm[5] = array('00:00','자정');
$vtm[7] = array($twr   ,'천문박명');
$vtm[9] = array($sunr  ,'일출');

$mrkey mrskey($JD0,$mriseJD,$sunrJD,$sunsJD,$twrJD,$twsJD);
$mskey mrskey($JD0,$msetJD ,$sunrJD,$sunsJD,$twrJD,$twsJD);

$cc = array();
for(
$i=3$i<=7$i++) $cc[$i] = 'class=dark';

if(
$mriseJD $JD0)  // 오후~자정 사이에 월출인 경우
{
  if(
$mrkey $mskey// 월출 -> 월몰
  
{
    
$endgrey min($mskey,8);
    for(
$i=($mrkey+1); $i<$endgrey$i++) $cc[$i] = 'class=grey';
  }
  else 
// 월몰 -> 월출
  
{
    for(
$i=($mrkey+1); $i<=7$i++) $cc[$i] = 'class=grey';
  }
}
else 
// 자정~오전 사이에 월출인 경우
{
  for(
$i=($mrkey+1); $i<=7$i++) $cc[$i] = 'class=grey';
  if(
$mrkey $mskey)  // 월몰 -> 월출
  
{
    for(
$j=3$j<$mskey$j++) $cc[$j] = 'class=grey'// add more grey
  
}
}

// override
$cc[0] = $cc[10] = ''// white
$cc[1] = $cc[2] = $cc[8] = $cc[9] = 'class=grey';

$vtm[$mrkey] = array($mrise,'월출');
$vtm[$mskey] = array($mset ,'월몰');

$moonimg "<img src=moonage/moonage-$moonagep.gif width=20 height=20 alt='월령 $moonage'>";
if(
$mrkey $mskey)
{
  for(
$i=$mrkey$i<=$mskey$i++) $vta[$i] = $moonimg;
}
else
{
  for(
$i=0$i<=$mskey$i++)  $vta[$i] = $moonimg;
  for(
$i=$mrkey$i<=10$i++) $vta[$i] = $moonimg;
}
if(!isset(
$vtm[0]))  $vta[0]  = '';
if(!isset(
$vtm[10])) $vta[10] = '';

// to white 0 1 2 (3 4 5 6 7) 8 9 10

$mdarkh str_replace(':','h ',astro::h2hm($mdark)).'m';
$mdarkp = ($dark>0) ? sprintf('%d',($mdark*100)/$dark) : 0;
$mdarkpclass = array('bad','some','better','good''best');
$mdarkpclass $mdarkpclass[min(floor($mdarkp/25),4)];

## moon current pos
##
list($mposp,$mpos) = moon_pos_simple($JD,$loc,'-');

$mooninfo = array
(
  
'Moon',        // messier
  
"<img src=moonage/moonage-$moonagep.gif>",
  
0,            // marathon
  
'-',            // 별자리
  
'위성',        // type
  
$mposp,        // 밝기 아님
  
$mposp,        // 현재 위치/고도
  
$mrp.$mrise,        // rise
  
$mcul,        // 남중
  
$msp.$mset,        // set
  
'',
  
'',
);

$addmore = array('ufind','uview','tele');
$messier_current_pos stellar::messier_current_pos($JD,$loc,$addmore);  // 'messier/%s-s.gif'
$messier_current_pos['pos'][$mpos] = array_merge(array($mooninfo),$messier_current_pos['pos'][$mpos]); // add to first
list($poss_header,$poss_all) = stellar::messier_current_pos2simple($messier_current_pos,1);

$messier_current_pos['pos'][$mpos][0][5] = '-';  // moon mag to '-'

$vpos "$loc[0]$loc[1] ($loc[2])";
$vtime $messier_current_pos['loc'][1];
$selm[(int)$_m] = $seld[(int)$_d] = $selh[(int)$_h] = $seli[(int)$_i] = 'SELECTED';

echo 
"<div class=solidbox>";
echo 
"<TABLE BORDER=0 CELLSPACING=4 class=0tset CELLPADDING=3 WIDTH=800><TR>";
echo 
"<FORM METHOD=get><TD class=bold>시각 설정: </TD>";
echo 
"<TD><INPUT TYPE=text NAME='_y' id=_y VALUE='$_y' SIZE=5 MAXLENGTH=5>년</TD>\n";

echo 
"<TD><SELECT NAME='_m' id=_m>\n";
for(
$i=1$i<=12$i++) printf("<OPTION VALUE=%02d ".($selm[$i]??'').">%02d월</OPTION>",$i,$i);

$endday calendar::days_in_month($_y,$_m);
echo 
"</SELECT></TD><TD><SELECT NAME='_d' id=_d>\n";
for(
$i=1$i<=$endday$i++) printf("<OPTION VALUE=%02d ".($seld[$i]??'').">%02d일</OPTION>",$i,$i);

echo 
"</SELECT></TD><TD><SELECT NAME='_h' id=_h>\n";
for(
$i=0$i<=23$i++) printf("<OPTION VALUE=%02d ".($selh[$i]??'').">%02d시</OPTION>",$i,$i);

echo 
"</SELECT></TD><TD><SELECT NAME='_i' id=_i>\n";
for(
$i=0$i<=55$i+=5)  printf("<OPTION VALUE=%02d ".($seli[$i]??'').">%02d분</OPTION>",$i,$i);
echo 
"</SELECT></TD><TD nowrap align=right>\n";
?>
<INPUT TYPE=button id=setto  class=pointer VALUE='이 시각으로 계산'>&nbsp;
<INPUT TYPE=reset  id=reset  class=pointer VALUE='초기화(Reset)'>&nbsp;
<INPUT TYPE=button id=currto class=pointer VALUE='현재 시각으로 계산'>
</TD></TR>
<TR>
<TD class=bold>미세 설정: </TD><TD COLSPAN=2>&nbsp;</TD><TD align=center
><img id='dback' class=pointer src='/images/control_back.png' border=0 valign=middle
>일<img id='dforward' class=pointer src='/images/control_forward.png' border=0 valign=middle
></TD><TD align=center><img id='hback' class=pointer src='/images/control_back.png' border=0 valign=middle
>시<img id='hforward' class=pointer src='/images/control_forward.png' border=0 valign=middle>
</TD></FORM><TD COLSPAN=2>&nbsp;</TD></TR>
<?php
$todaymark
[1] ??= '';
$printw[1]    ??= '';
echo 
"<TR><TD class=bold>관측 위치:</TD><TD COLSPAN=6><span id=loc>$vpos</span> <span id=setloc>[&laquo;변경하기] <img class=vmiddle src=/images/acc1.gif border=0 align=middle></span>".
    
"</TD></TR>\n";
echo 
"<TR><TD class=bold>관측 시각:</TD><TD COLSPAN=6>$vtime</TD></TR>\n";
echo 
"<TR><TD COLSPAN=7 class=smallfont>*참고) 북극성 위치(적도의 극축 정렬용): NCP에서 $polar 방향(정립상) 또는 $polarr 방향(극망용)</TD></TR>\n";
echo 
"</TABLE></div>\n";

$todaymark[0] ??= '';
$printw[0]    ??= '';
$todaymark[1] ??= '';
$printw[1]    ??= '';

echo 
"<P>\n";
echo 
"<TABLE BORDER=1 class=tim CELLSPACING=4 CELLPADDING=2>\n";
echo 
"<TR>\n";
echo 
"<TD COLSPAN=5 align=center $todaymark[0]>$printw[0]</TD><TD COLSPAN=6 align=center $todaymark[1]>$printw[1]</TD>";
echo 
"<TD width=120>관측 가능 시간</TD>";
echo 
"</TR>\n";

echo 
"<TR class=vtfcolor>\n";
for(
$i=0$i<=10$i++) echo '<TD width=44 '.$cc[$i].'>'.($vtm[$i][0] ?? '').'</TD>';
echo 
"<TD class=dark>dark $mdarkh</TD>";
echo 
"</TR>\n";

echo 
"<TR class=smallfont>\n";
for(
$i=0$i<=10$i++) echo '<TD width=44 '.$cc[$i].'>'.($vtm[$i][1] ?? '').'</TD>';
echo 
"<TD class=$mdarkpclass>{$mdarkp}% (dark)</TD>";
echo 
"</TR>\n";

echo 
"<TR class=smallfont>\n";
for(
$i=0$i<=10$i++) echo '<TD width=44 '.$cc[$i].'>'.($vta[$i] ?? '').'</TD>';
echo 
"<TD>월령 $moonage (local 0시 기준)</TD>";
echo 
"</TR>\n";
echo 
"</TABLE><P>\n";

echo <<<__END
<div class="comment">
*주) <span id=cmtclose class=showhide>&laquo;감추기</span>
<pre id=cmt>
Object: Mxx(메시에 목록), Gxxxx(NGC 목록)
ufind: 도시에서 6x50 파인더로 찾을 경우
uview: 도시에서 8" 반사망원경의 36배율로 볼 경우
tele: "Atlas of Messier Objects-Highlights of the deep sky" 기준
*시각: 지평선 위에 항상 떠 있는 경우
+시각: 다음날 시각
-시각: 이전날 시각
</div>
<P>
__END;

$tdw floor($_tablewidth/sizeof($poss_header));
$visible_count $messier_current_pos['visible_count'];
$height_fixed  = (sizeof($poss_all)+1) * 36;

$possp  $tab_pos '';
$tabidx 2;
foreach(
$poss_header AS $v)
{
  if(
$v == '-'$v 'yet';
  
$possp   .= "<TD width=${tdw} class=tabchanger style='cursor:pointer' tabidx='tab-{$tabidx}'>$v</TD>";
  
$tab_pos .= "<div class=menu tabidx='tab-{$tabidx}' id='tabmenu-tab-{$tabidx}'>$v</div>\n";
  
$tabidx++;
}

echo 
"<div class='tabs' style='height:".$height_fixed."px'>\n";
echo 
"<div class='current menu' tabidx='tab-1' id='tabmenu-tab-1' style='width:64px'>하늘전체</div>\n";
echo 
$tab_pos;
echo 
"<div class=thin-line></div>\n";

echo 
"<div id='tab-1' class='tab-content current'><p>";
echo 
'[<b>현재 하늘 전체 '.$visible_count."개]</b> - $vtime";
echo 
"<TABLE BORDER=1 WIDTH=$_tablewidth class=ttcl id=allsky>\n";
echo 
"<TR class=thcl>$possp</TR>\n";
foreach(
$poss_all AS $arr) echo '<TR><TD>'.implode("</TD><TD>",$arr)."</TD></TR>\n";
echo 
"</TABLE>\n";
echo 
"<P>\n";
echo 
"</div>\n";

array_insert($messier_current_pos['pos_header'],1,'pic');
$tsize sizeof($messier_current_pos['pos_header']);
$bsize $tsize sizeof($addmore);
$thw   floor($_tablewidth/$tsize);
$posh  "<TR class=thcl><TH width=${thw}>".implode("</TH><TH width=${thw}>",$messier_current_pos['pos_header'])."</TH></TR>\n";

$nfinds = array
(
  
=> array('<span class=tohide>0</span>쉬움','easy'),
  
=> array('<span class=tohide>1</span>보통','normal'),
  
=> array('<span class=tohide>2</span>어려움','difficult'),
  
=> array('<span class=tohide>3</span>도전','challenge'),
  
=> array('<span class=tohide>4</span>못찾음','notfind'),
  
'' => array('<span class=tohide>99</span>-','notfind')
);

$nviews = array
(
  
=> array('<span class=tohide>0</span>잘보임','easy'),
  
=> array('<span class=tohide>1</span>보통','normal'),
  
=> array('<span class=tohide>2</span>형태만','difficult'),
  
=> array('<span class=tohide>3</span>안보임','notview'),
  
'' => array('<span class=tohide>99</span>-','notview')
);

$tabidx 2;
foreach(
$messier_current_pos['pos'] AS $pos=>$arr)
{
  if(
$pos == '-')
  {
    
$tid   'tsortyet';
    
$ptext '[이미 지거나 아직 안뜸]';
  }
  else
  {
    
$tid   'tsort'.$pos;
    
$ptext "[$pos 방향] 메시에 목록";
  }

  echo 
"<div id='tab-{$tabidx}' class='tab-content'><p>";
  echo 
"<a name='{$tid}a'><b>$ptext</b></a>&nbsp;&nbsp;";
  echo 
"<TABLE BORDER=1 class=tbcl id='$tid'>\n";
  echo 
"<THEAD>$posh</THEAD>\n<TBODY>";

  foreach(
$arr AS $j=>$posv)
  {
    if(
is_numeric($posv[1]))  // skip moon, aleray done
    
{
        
$tryfile 'messier/'.$posv[0].'-s.gif';
        
$imgsrc  file_exists($tryfile) ? "<img src='$tryfile' class=viewlimg>" '-';
        
array_insert($posv,1,$imgsrc);
    }
    echo 
'<TR>';
    for(
$i=0$i<$bsize$i++) echo "<TD nowrap>$posv[$i]</TD>";
    foreach(
$addmore AS $name// addmore
    
{
        
$k $posv[$i] ?? '';  // '' it's moon
        
list($v,$class) = ($name=='ufind') ? $nfinds[$k] : $nviews[$k];
        echo 
"<TD class='$class' nowrap>$v</TD>";
        
$i++;
    }
    echo 
"</TR>\n";
  }
  echo 
"</TBODY>\n</TABLE>\n";
  echo 
"<P>\n";
  echo 
"</div>\n";
  
$tabidx++;
}

echo 
"</div><p>\n";  // end tabs
echo "</BODY></HTML>";

return;
?>

Page loading: 0.01(server) + (network) + (browser) seconds