Странно. Вне зависимости от того, являетесь ли вы сторонником теории биоритмов или нет, решение данной задачки вполне способно представлять интерес, особенно для студентов-абитуриентов... ну ок, пусть будет хотя б одно.
Считать биоритмы будем, исходя из формулы:
B = (sin(2π*t/P))*100%
, где
P = {23,28,33},
B — искомые состояния биоритма (%),
t — количество дней, прошедших с даты рождения до текущего момента.
После некоторых меланхоличных размышлений приходим к вот такому классу, naming которого говорит (надеюсь) сам за себя:
class BiorhythmsCalc
def self.get_values_and_dates(b)
values = []
[23, 28, 33].each do |x|
values << BiorhythmsCalc.biorhythm_counter(x, todays_date(b))[0]
end
dates = BiorhythmsCalc.biorhythm_counter(x = 23, todays_date(b))[1].map { |e| "`#{e}`" }.join(', ')
[values, dates]
end
def self.biorhythm_counter(*args)
arr1 = []
arr2 = []
(-3..15).each do |x|
arr1 << calculation(x, args[1], args[0])
arr2 << get_date_period(x)
end
[arr1, arr2]
end
def self.calculation(*args)
(Math.sin(2 * Math::PI * BiorhythmsCalc.day_counter(args[0], args[1].to_date) / args[2]) * 100).round(2)
end
def self.get_date_period(x)
(Date.today + x).to_formatted_s(:short)
end
def self.day_counter(*args)
Integer(Date.today + args[0] - args[1])
end
def self.todays_date(b)
Date.strptime(b, '%d-%m-%Y')
end
def self.flash_message(b)
'Today, ' +
Time.new.strftime('%d of %B, %Y').to_s +
', you have lived ' +
BiorhythmsCalc.day_counter(0, todays_date(b)).to_s +
' days.'
end
end
Итак, вызов того или иного метода класса BiorhythmsCalc, с передачей соответствующего параметра (все, что необходимо - дата дня рождения), возвращает массивы дат и значений трех биоритмов; дополнительно можно получить количество дней, прожитых со дня рождения (пригодится для вывода flash-сообщения):
arr = BiorhythmsCalc.get_values_and_dates(params[:birthday])
@values = arr[0]
@dates = arr.delete_at(1)
flash.now[:notice] = BiorhythmsCalc.flash_message(params[:birthday])
На основе полученных значений строим график и/или таблицу, результаты можно взглянуть на живой демке. В табличке подсвечиваем строки, даты которых приходятся на т. н. "критические дни":
<script>
let trs = document.querySelectorAll('tbody>tr')
for (let i=0; i<trs.length-1; i++) {
let v1 = parseFloat(trs[i].children[1].textContent)
let v2 = parseFloat(trs[i+1].children[1].textContent)
let v3 = parseFloat(trs[i].children[2].textContent)
let v4 = parseFloat(trs[i+1].children[2].textContent)
let v5 = parseFloat(trs[i].children[3].textContent)
let v6 = parseFloat(trs[i+1].children[3].textContent)
if (v1 ==0 || v1*v2 < 0) trs[i].style.background = '#ffcccc'
if (v3 ==0 || v3*v4 < 0) trs[i].style.background = '#ffcccc'
if (v5 ==0 || v5*v6 < 0) trs[i].style.background = '#ffcccc'
}
</script>
Примечание: для построения графика использован Highcharts. Spline with symbols, предоставляющий возможность, при необходимости, отмечать на графике те или иные точки, в зависимости от условий. Воспользуйтесь этим свойством скрипта, если сочтете необходимым:
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, {
y: 26.5,
marker: {
symbol: 'url(https://www.highcharts.com/samples/graphics/sun.png)'
}
}, 23.3, 18.3, 13.9, 9.6]
},