ИнформАрхив QSP

Календарь по методу счёта Юлианский дней

Календарь по рецепту evp. Синтетическая статья, основанная на серии сообщений.

Давным-давно были разработаны формулы для вычисления точной календарной даты из Юлианской даты. Юлианская дата — это число, показывающее, сколько точно прошло дней, начиная с полудня понедельника 24 ноября 4714 года до нашей эры.

Для тех, кто интересуется теорией, на википедии есть замечательная статья, всё подробно разъясняющая. Нас же интересуют непосредственно формулы, и что мы из них можем получить.

evp уже переложил все необходимые расчёты на QSP. Следующий код достаточно просто скопировать на отдельную локацию, и его можно тут же начать использовать. Для примера, будем считать, что данный код находится на локации "calendar".

JDN = JDNStart + time/1440
hour = (time/60) MOD 24
minut = time MOD 60
weekday = (JDN MOD 7) + 1

JDa = JDN + 32044
JDb = (4*JDa + 3)/146097
JDc = JDa - (146097*JDb/4)
JDd = (4*JDc + 3)/1461
JDe = JDc - 1461*JDd/4
JDm = (5*JDe + 2)/153

day = JDe - (153*JDm+2)/5 + 1
month = JDm + 3 - 12*(JDm/10)
year = 100*JDb + JDd - 4800 + JDm/10
$hour_text = iif (hour < 10, '0<<hour>>', '<<hour>>')
$minut_text = iif (minut < 10, '0<<minut>>', '<<minut>>')

В самом начале игры нам нужно задать переменные JDNStart и time. Именно эти переменные будут хранить точное значение времени в нашей игре.

JDNStart показывает, когда наша игра должна начаться. Эта переменная содержит число дней, прошедших с полудня понедельника 24 ноября 4714 года д.н.э и до начала нашей игры.

К примеру, наша игра должна начаться 7 ноября 1917 года, в среду. Открываем калькулятор. Подставляем в нужные поля дату 7 ноября 1917, а время пишем 12 часов 00 минут 00 секунд. Юлианский день начинается с полудня! И получаем число 2421540. Точное, без дробной части, число дней.

Это самое число и есть наш JDNStart, вот и записываем 2421540 в переменную.

А в переменную time мы записываем, соответственно, число минут, прошедших с начала стартового дня нашей игры (не от полудня, а от полуночи). Например, наша игра стартует в 15:37. Значит с начала дня прошло 15 часов 37 минут, и значит на старте игры мы должны в переменную time записать число 15*60+37.

Итого мы будем иметь две строчки кода на самой первой локации в нашей игре, описывающие время:

JDNStart=2421540
time=15*60+37

Помимо JDNStart и time на самой первой локации нужно ещё прописать в отдельные массивы текстовое представление для дней недели и месяцев:

$weekday_text[1] = 'Понедельник'
$weekday_text[2] = 'Вторник'
$weekday_text[3] = 'Среда'
$weekday_text[4] = 'Четверг'
$weekday_text[5] = 'Пятница'
$weekday_text[6] = 'Суббота'
$weekday_text[7] = 'Воскресенье'
$month_text[1] = 'Январь'
$month_text[2] = 'Февраль'
$month_text[3] = 'Март'
$month_text[4] = 'Апрель'
$month_text[5] = 'Май'
$month_text[6] = 'Июнь'
$month_text[7] = 'Июль'
$month_text[8] = 'Август'
$month_text[9] = 'Сентябрь'
$month_text[10] = 'Октябрь'
$month_text[11] = 'Ноябрь'
$month_text[12] = 'Декабрь'

И вот теперь всё готово для того, чтобы мы могли пользоваться полноценным календарём в нашей игре.

Дальше всё просто. Каждый раз, когда мы совершаем действие, которое должно занять какое-то время, в коде этого действия необходимо предусмотреть изменение переменной time. Например:

act 'Ехать в Смольный':
    time += 45
    gt 'smolny'
end

Нажав на действие, мы изменим значение переменной time, т.е. переместимся во времени на 45 минут, и с помощью оператора goto переместимся на локацию "smolny".

Чтобы увидеть то самое изменение времени на экране, мы должны просто вызвать код локации "calendar", чтобы все значения пересчитались, а затем вывести нужные значения на экран. Например, так:

gs 'calendar'
*nl $weekday_text[weekday] + ',' + day + $month_text[month] + ' ' + year + 'года' + '. ' + $hour_text + ':' + $minut_text

Этот алгоритм хорошо работает на датах от 1 г. н.э. и дальше. Но если мы хотим его использовать для отображения дат до нашей эры, то нужно добавить вот эту строчку в самый конец локации "calendar":

$year_text = iif (year < 1, '<<-year+1>> г. до н.э.', '<<year>> г.'))

Это становится необходимым, если вы действительно хотите, чтобы отображение дат полностью соответствовало Григорианскому календарю. Дело тут в том, что алгоритм вычисляет астрономический счет лет, при котором за -1-м годом следует нулевой год, а затем 1-й год. В Григорианском же календаре принято, что первому году н.э. предшествовал 1-й год до н.э. Нулевого года в Григорианском календаре нет.

Для закрепления понимания того, как это всё работает, напишите несколько локаций:

Локация "smolny"

*nl'Смольный'
*nl $weekday_text[weekday] + ', ' + day + ' ' + $month_text[month] + ' ' + year + 'года' + '.  ' + $hour_text + ':' + $minut_text
    act 'Ехать на вокзал':
        time += 45
        gs 'calendar' 
        gt 'station'
    end

Локация "station"

*nl'Вокзал'
*nl $weekday_text[weekday] + ', ' + day + ' ' + $month_text[month] + ' ' + year + 'года' + '.  ' + $hour_text + ':' + $minut_text
    act 'Ехать в Смольный':
        time += 45
        gs 'calendar' 
        gt 'smolny'
    end
    act 'Ехать в Москву (время в пути 1 сутки, 3 часа)':
        time += 1620
        gs 'calendar' 
        gt 'moscow'
    end

Локация "moscow"

*nl'Москва'
*nl $weekday_text[weekday] + ', ' + day + ' ' + $month_text[month] + ' ' + year + 'года' + '.  ' + $hour_text + ':' + $minut_text
    act 'Ехать в Питер (время в пути 1 сутки, 3 часа 45 минут)':
        time += 1665
        gs 'calendar' 
        gt 'station'
    end

В стартовой локации напишите этот код:

! задаём начальное время
JDNStart=2421540
time=3*60+37
! прописываем в массив названия месяцев и дней недели
$weekday_text[1] = 'Понедельник'
$weekday_text[2] = 'Вторник'
$weekday_text[3] = 'Среда'
$weekday_text[4] = 'Четверг'
$weekday_text[5] = 'Пятница'
$weekday_text[6] = 'Суббота'
$weekday_text[7] = 'Воскресенье'
$month_text[1] = 'Январь'
$month_text[2] = 'Февраль'
$month_text[3] = 'Март'
$month_text[4] = 'Апрель'
$month_text[5] = 'Май'
$month_text[6] = 'Июнь'
$month_text[7] = 'Июль'
$month_text[8] = 'Август'
$month_text[9] = 'Сентябрь'
$month_text[10] = 'Октябрь'
$month_text[11] = 'Ноябрь'
$month_text[12] = 'Декабрь'
! пересчитываем значения времени
gs 'calendar'
! переносимся  в Смольный
gt 'smolny'

Пробуйте запустить и следите за датой 🙂