Hello! There is a task:

There is a site where you can select and grow crystals. For example, chose a crystal. They pressed the "grow" button. A value was recorded in the database - the time when the growth began. The crystals have a growth time (10 days for example). In order for a stone to grow faster, you can buy growth percentages. If we buy 1 percent growth - the start time is postponed a certain time ago. How can I find this time and how to find the percentage of readiness that will be after the start time is updated.

Perhaps there is another approach to find how much, as a percentage, the crystal grew after each page refresh and how much time was left for the crystal to grow.

I was helped to find a solution formula:

{время_старта} - ( (10*24*60) * 0.01) = новое время старта (10*24*60) / ({сейчас} - {новое время старта}) * 100 = текущий процент. 

Trying to perform operations with dates:

 $новое_время_старта= date( 'Ymd h:i:s', strtotime($исходное_значение_времени_старта) - ( (10*24*60) * 0.01)); $date = date('Ymd H:i:s'); $текущий_процент = (10*24*60) / date( 'Ymd h:i:s', (strtotime($date) - strtotime($новое_время_старта)) * 100); 

If the new start time value is calculated, it seems to me, true, then with percentages the result is completely wrong.

Help please solve the problem.

#

It seems he did everything as suggested by Sergiks, but the result is not the same ..

What we know now: $ days - the term of crystal growth in days

And so, they chose a crystal and pressed the button to grow. :

 $time = time(); $start = new DateTime('@' . $time); $finish = new DateTime('@' . ($start + 86400 * $days)); $tsStart = date_timestamp_get($start); $tsFinish = date_timestamp_get($finish); 

$ tsStart and $ tsFinish - recorded in the database (in the form of int).

Further, we can see the current percentage of readiness with each page refresh. We think so:

 $now = time(); $progress = (time() - $tsStart) / ($tsFinish - $tsStart); if( $progress >= 1) { // вырос, забирайте } else { // готовность 100 * $progress процентов } 

When buying interest ($ procent), we finish the finish time like this:

 $finish = new DateTime('@' . ($tsStart + (1 - $procent / 100) * 86400 * $days)); 

And write to the database:

 $tsFinish = date_timestamp_get($finish); 

And the percentage of readiness is also calculated:

 $now = time(); $progress = (time() - $tsStart) / ($tsFinish - $tsStart); if( $progress >= 1) { // вырос, забирайте } else { // готовность 100 * $progress процентов } 

But the result is always different, there are even negative values. Tell me please, where was I wrong?

    2 answers 2

    In PHP, time is often counted in seconds, and so will we.

    It is known: the time of the beginning of the growth of $start in seconds since the beginning of the Unix epoch, obtained by the function time() ; and the duration of growth in days of $days , which will translate into seconds 86400 * $days and get the DateTime object of the finish date:

     $finish = new DateTime('@' . ($start + 86400 * $days)); 

    When we bought the “accelerator” by 1%, the start was the same, and the path from the start to the finish was shortened, became 0.99 * 86400 * $days . And the new finish is as follows:

     $finish = new DateTime('@' . ($start + 0.99 * 86400 * $days)); 

    In the database, you save $start and the current value of $finish , or rather, their integer values ​​of unix timestamp:

     $tsStart = $start->getTimestamp(); $tsFinish = $finish->getTimestamp(); 

    At the next visit, you extract them from the database, you know how much time is now, and consider the progress as a simple proportion:

     $now = time(); $progress = ($now - $tsStart) / ($tsFinish - $tsStart); // 0..1 if( $progress >= 1) { // вырос, забирайте } else { // готовность 100 * $progress процентов } 

    Above, all calculations were in seconds, and, by and large, there is no need to communicate with DateTime objects, but they help a lot in situations where, for example, you need to add two weeks to a date, mess with time zones, calculate the difference between two dates.

    • Option when $ finish is not saved in the database, and is calculated before the withdrawal is not considered? (save only the facts of purchase "accelerator"). In this case, it would be possible to correct errors without losing information .. - Vladimir Gamalyan
    • @VladimirGamalian did not consider. First, what kind of mistakes are we talking about? Errors should not be in principle. Secondly, in the working draft, a similar situation was recently decided exactly in this way: although the data can be calculated, we store the actual values, since reading the result is much more likely than writing or rechecking. - Sergiks
    • For example, the wrong formula was entered, or decided to revise the coefficients. Or even worse, some additional modifiers have been introduced that are intertwined with existing ones in a cunning way .. And what is read more often than what is written is usually solved by memorization / caching. Those. In the database, information is stored that will not change - the fact of purchase. And then you can turn it as you like. Otherwise, some information may be lost, which may suddenly come in handy. In such games, by the way, a continuous process - the alignment of balance. - Vladimir Gamalyan

    Let growth time be 10 days, it is 24 hours * 10 = 240 hours

    mean 1 percent growth is 2.4 hours

    let's say starting time 08/10/2016 13-40

    let's say bought 2 percent is 4.8 hours

    Of course time 08/20/2016 13-40

    subtract growth percentage from it and get time